|
|
@@ -2,13 +2,19 @@ package com.malk.minglei.service.impl.port;
|
|
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.malk.minglei.config.YidaApplicationsProperties;
|
|
|
+import com.malk.minglei.dto.EmployeeRosterInfo;
|
|
|
import com.malk.minglei.dto.MingleiPortRequest;
|
|
|
-import com.malk.minglei.service.approval.DingTalkApprovalClient;
|
|
|
+import com.malk.minglei.service.employee.EmployeeRosterService;
|
|
|
import com.malk.minglei.service.port.MingleiPortService;
|
|
|
import com.malk.minglei.service.port.SupplierPriceApprovalProcessService;
|
|
|
-import com.malk.service.dingtalk.DDClient;
|
|
|
+import com.malk.minglei.service.yida.YidaFormInstanceClient;
|
|
|
+import com.malk.minglei.service.yida.YidaProcessOpenApiClient;
|
|
|
+import com.malk.server.common.McException;
|
|
|
+import com.malk.server.dingtalk.DDR_New;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.web.client.RestClientException;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
@@ -25,22 +31,31 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
- * 将指定宜搭供应商价格审批流程实例转换为 T100 核价单请求。
|
|
|
+ * 将指定宜搭流程实例转换为对应的 T100 单据请求。
|
|
|
*
|
|
|
- * <p>字段 ID 和 T100 字段的对应关系来自《供应商价格审批单(核价)字段清单》;
|
|
|
- * 该类仅负责读取、转换和转发,不修改宜搭流程数据。
|
|
|
+ * <p>该类读取宜搭表单实例数据、转换并推送 T100;四张供应商价格审批单推送成功后回写 ERP 单号。
|
|
|
*/
|
|
|
@Service
|
|
|
public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApprovalProcessService {
|
|
|
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(SupplierPriceApprovalProcessServiceImpl.class);
|
|
|
+ //供应商价格审批单(核价)
|
|
|
private static final String SUPPLIER_PRICE_APPROVAL_FORM_ID = "FORM-468B6FB2D5BF490A8BC6DBD6FAF9BCCA28R9";
|
|
|
+ //供应商价格审批单(暂估)
|
|
|
private static final String ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID = "FORM-F906C997A4A44DC8B9180198C0B2E55F6W0S";
|
|
|
+ //供应商价格审批单(子公司核价)
|
|
|
private static final String SUBSIDIARY_SUPPLIER_PRICE_APPROVAL_FORM_ID = "FORM-C09818E73B1640A9AA9F6D7F55C47612EFV8";
|
|
|
+ //供应商价格审批单(子公司暂估)
|
|
|
private static final String SUBSIDIARY_ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID = "FORM-EC46C7109182497796AA0B70F3848576UYBU";
|
|
|
+ private static final String PACKAGING_MATERIAL_PRICE_APPROVAL_FORM_ID = "FORM-69A12600F87349D3B653BF86E419224DLIX9";
|
|
|
+ private static final String SUPPLIER_SUSPEND_EXIT_FORM_ID = "FORM-0A05D30C6E0745EC9F4B74D0E038EE73O7B6";
|
|
|
+ private static final String PACKAGING_MATERIAL_ITEM_LIST_FORM_ID = "FORM-F88BDA6B3A114E668AD5A6347AE4E01C91O9";
|
|
|
+ private static final String PACKAGING_MATERIAL_PRICE_APPROVAL_TYPE = "priceSheets";
|
|
|
+ private static final String SUPPLIER_SUSPEND_EXIT_TYPE = "suspensionExit";
|
|
|
+ private static final String PACKAGING_MATERIAL_ITEM_LIST_TYPE = "partNumberListAudit";
|
|
|
private static final Map<String, SupplierPriceApprovalFormMapping> FORM_MAPPINGS = createFormMappings();
|
|
|
+ private static final Map<String, String> T100_DOCUMENT_NUMBER_WRITE_BACK_FIELDS = createT100DocumentNumberWriteBackFields();
|
|
|
|
|
|
- private static final String DEFAULT_ESTIMATED_FLAG = "N";
|
|
|
private static final String DEFAULT_DOCUMENT_STATUS = "I";
|
|
|
private static final ZoneId BUSINESS_ZONE = ZoneId.of("Asia/Shanghai");
|
|
|
private static final List<DateTimeFormatter> DATE_FORMATTERS = Arrays.asList(
|
|
|
@@ -48,9 +63,11 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
DateTimeFormatter.ofPattern("yyyy/M/d"),
|
|
|
DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
|
|
|
|
|
- private final DDClient dingTalkClient;
|
|
|
- private final DingTalkApprovalClient approvalClient;
|
|
|
+ private final YidaFormInstanceClient yidaFormInstanceClient;
|
|
|
+ private final YidaProcessOpenApiClient yidaProcessOpenApiClient;
|
|
|
+ private final YidaApplicationsProperties.ApplicationCredentials coordinationOfficeConfiguration;
|
|
|
private final MingleiPortService mingleiPortService;
|
|
|
+ private final EmployeeRosterService employeeRosterService;
|
|
|
private final ObjectMapper objectMapper;
|
|
|
|
|
|
/**
|
|
|
@@ -60,48 +77,69 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
*/
|
|
|
private static Map<String, SupplierPriceApprovalFormMapping> createFormMappings() {
|
|
|
Map<String, SupplierPriceApprovalFormMapping> mappings = new LinkedHashMap<String, SupplierPriceApprovalFormMapping>();
|
|
|
+ //供应商价格审批单(核价)
|
|
|
mappings.put(SUPPLIER_PRICE_APPROVAL_FORM_ID, new SupplierPriceApprovalFormMapping(
|
|
|
- "employeeField_msh186rr", "selectField_mszqctpc", "serialNumberField_msmwc0yx",
|
|
|
- "dateField_mszqctpf", "associationFormField_mu9juhgz", "dateField_mszqctpx",
|
|
|
- "dateField_mszqctpy", "selectField_mszqctq2", "textField_mszqctqb",
|
|
|
- "tableField_mszqctqd", "associationFormField_mu9juhh0", "numberField_mszqctqh",
|
|
|
+ "employeeField_msh186rr", "selectField_mszqctpc", "textField_mvhhjsy8",
|
|
|
+ "dateField_mszqctpf", "textField_mvius864", "dateField_mszqctpx",
|
|
|
+ "dateField_mszqctpy", "selectField_mszqctq2", "serialNumberField_msmwc0yx",
|
|
|
+ "tableField_mszqctqd", "selectField_mvhrhghk", "numberField_mszqctqh",
|
|
|
"textField_mszqctql"));
|
|
|
+ //供应商价格审批单(暂估)
|
|
|
mappings.put(ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID, new SupplierPriceApprovalFormMapping(
|
|
|
- "employeeField_msh186rr", "selectField_mt7yf5x2", "serialNumberField_msmwc0yx",
|
|
|
- "dateField_mt7yf5w6", "selectField_mvanfd8c", "dateField_mt7yf5wm",
|
|
|
- "dateField_mt7yf5wn", "selectField_mt7yf5wo", "textField_mt7yf5wu",
|
|
|
- "tableField_msh186sv", "selectField_mvanfd8d", "numberField_mti2sdb4",
|
|
|
+ "employeeField_msh186rr", "departmentSelectField_msh186ry", "textField_mti3631t",
|
|
|
+ "dateField_mt7yf5w6", "textField_mvius864", "dateField_mt7yf5wm",
|
|
|
+ "dateField_mt7yf5wn", "selectField_mt7yf5wo", "serialNumberField_msmwc0yx",
|
|
|
+ "tableField_msh186sv", "selectField_mvanfd8d", "numberField_mt6viiqh",
|
|
|
"textField_mt6ur4w8"));
|
|
|
+ //供应商价格审批单(子公司核价)
|
|
|
mappings.put(SUBSIDIARY_SUPPLIER_PRICE_APPROVAL_FORM_ID, new SupplierPriceApprovalFormMapping(
|
|
|
- "employeeField_msh186rr", "selectField_mszqctpc", "serialNumberField_msmwc0yx",
|
|
|
- "dateField_mszqctpf", "selectField_mvejv4mx", "dateField_mszqctpx",
|
|
|
- "dateField_mszqctpy", "selectField_mszqctq2", "textField_mszqctqb",
|
|
|
+ "employeeField_msh186rr", "selectField_mszqctpc", "textField_mvhhkiyu",
|
|
|
+ "dateField_mszqctpf", "textField_mvius864", "dateField_mszqctpx",
|
|
|
+ "dateField_mszqctpy", "selectField_mszqctq2", "serialNumberField_msmwc0yx",
|
|
|
"tableField_mszqctqd", "selectField_mvejv4mz", "numberField_mszqctqh",
|
|
|
"textField_mszqctql"));
|
|
|
+ //供应商价格审批单(子公司暂估)
|
|
|
mappings.put(SUBSIDIARY_ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID, new SupplierPriceApprovalFormMapping(
|
|
|
- "employeeField_msh186rr", "selectField_mt7yf5x2", "serialNumberField_msmwc0yx",
|
|
|
- "dateField_mt7yf5w6", "selectField_mvf0cizj", "dateField_mt7yf5wm",
|
|
|
- "dateField_mt7yf5wn", "selectField_mt7yf5wo", "textField_mt7yf5wu",
|
|
|
+ "employeeField_msh186rr", "selectField_mt7yf5x2", "textField_mvhhbywg",
|
|
|
+ "dateField_mt7yf5w6", "textField_mvius864", "dateField_mt7yf5wm",
|
|
|
+ "dateField_mt7yf5wn", "selectField_mt7yf5wo", "serialNumberField_msmwc0yx",
|
|
|
"tableField_msh186sv", "selectField_mvf0cizk", "numberField_mt6viiqh",
|
|
|
"textField_mt6ur4w8"));
|
|
|
return Collections.unmodifiableMap(mappings);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 创建流程实例转 T100 核价单服务。
|
|
|
+ * 注册各供应商价格审批单的 T100 单号回写字段。
|
|
|
+ */
|
|
|
+ private static Map<String, String> createT100DocumentNumberWriteBackFields() {
|
|
|
+ Map<String, String> fields = new LinkedHashMap<String, String>();
|
|
|
+ fields.put(SUPPLIER_PRICE_APPROVAL_FORM_ID, "textField_mszqctqb");
|
|
|
+ fields.put(ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID, "textField_mt7yf5wu");
|
|
|
+ fields.put(SUBSIDIARY_SUPPLIER_PRICE_APPROVAL_FORM_ID, "textField_mszqctqb");
|
|
|
+ fields.put(SUBSIDIARY_ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID, "textField_mt7yf5wu");
|
|
|
+ return Collections.unmodifiableMap(fields);
|
|
|
+ }
|
|
|
+//
|
|
|
+ /**
|
|
|
+ * 创建宜搭流程实例转 T100 单据服务。
|
|
|
*
|
|
|
- * @param dingTalkClient 钉钉客户端,用于获取访问令牌
|
|
|
- * @param approvalClient 审批实例查询客户端
|
|
|
- * @param mingleiPortService T100 核价单推送服务
|
|
|
+ * @param yidaFormInstanceClient 宜搭表单实例查询客户端
|
|
|
+ * @param mingleiPortService T100 单据推送服务
|
|
|
+ * @param employeeRosterService 员工花名册查询服务
|
|
|
* @param objectMapper JSON 解析器
|
|
|
*/
|
|
|
- public SupplierPriceApprovalProcessServiceImpl(DDClient dingTalkClient,
|
|
|
- DingTalkApprovalClient approvalClient,
|
|
|
+ public SupplierPriceApprovalProcessServiceImpl(
|
|
|
+ YidaFormInstanceClient yidaFormInstanceClient,
|
|
|
+ YidaProcessOpenApiClient yidaProcessOpenApiClient,
|
|
|
+ YidaApplicationsProperties applications,
|
|
|
MingleiPortService mingleiPortService,
|
|
|
+ EmployeeRosterService employeeRosterService,
|
|
|
ObjectMapper objectMapper) {
|
|
|
- this.dingTalkClient = dingTalkClient;
|
|
|
- this.approvalClient = approvalClient;
|
|
|
+ this.yidaFormInstanceClient = yidaFormInstanceClient;
|
|
|
+ this.yidaProcessOpenApiClient = yidaProcessOpenApiClient;
|
|
|
+ this.coordinationOfficeConfiguration = applications.getCoordinationOffice();
|
|
|
this.mingleiPortService = mingleiPortService;
|
|
|
+ this.employeeRosterService = employeeRosterService;
|
|
|
this.objectMapper = objectMapper;
|
|
|
}
|
|
|
|
|
|
@@ -109,42 +147,398 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
* 查询流程详情,按已确认字段映射组装 T100 请求后推送。
|
|
|
*
|
|
|
* @param formId 宜搭表单 ID,用于选择字段映射规则
|
|
|
- * @param processInstanceId 宜搭流程实例 ID
|
|
|
+ * @param formInstanceId 宜搭表单实例 ID,用于读取表单数据
|
|
|
+ * @param processInstanceId 宜搭流程实例 ID,四张供应商价格审批单回写时必填
|
|
|
* @return T100 接口原始响应内容
|
|
|
*/
|
|
|
@Override
|
|
|
- public Map<String, Object> submitByProcessInstanceId(String formId, String processInstanceId) {
|
|
|
+ public Map<String, Object> submitByInstanceIds(String formId, String formInstanceId,
|
|
|
+ String processInstanceId) {
|
|
|
String requestedFormId = requireText(formId, "formId must not be blank");
|
|
|
- SupplierPriceApprovalFormMapping mapping = resolveFormMapping(requestedFormId);
|
|
|
- String instanceId = requireText(processInstanceId, "processInstanceId must not be blank");
|
|
|
- String accessToken = requireText(dingTalkClient.getAccessToken(), "Unable to obtain DingTalk access token");
|
|
|
- Map<String, Object> instanceDetail = approvalClient.getProcessInstanceDetail(accessToken, instanceId);
|
|
|
- Map<?, ?> result = requireMap(instanceDetail.get("result"), "Approval instance " + instanceId + " has no form data");
|
|
|
- validateFormUuid(result, requestedFormId, instanceId);
|
|
|
+ SupplierPriceApprovalFormMapping mapping = FORM_MAPPINGS.get(requestedFormId);
|
|
|
+ String dataKeyType = resolveDataKeyType(requestedFormId);
|
|
|
+ if (mapping == null && dataKeyType == null) {
|
|
|
+ throw new IllegalArgumentException("Unsupported supplier price approval formId: " + requestedFormId);
|
|
|
+ }
|
|
|
+ String requestedProcessInstanceId = mapping == null ? null : requireText(processInstanceId,
|
|
|
+ "processInstanceId must not be blank for supplier price approval forms");
|
|
|
+ String requestedFormInstanceId = requireText(formInstanceId, "formInstanceId must not be blank");
|
|
|
+ Map<?, ?> instanceDetail;
|
|
|
+ try {
|
|
|
+ instanceDetail = requireMap(yidaFormInstanceClient.getFormInstance(requestedFormId, requestedFormInstanceId),
|
|
|
+ "Yida form instance " + requestedFormInstanceId + " has no form data");
|
|
|
+ } catch (RestClientException exception) {
|
|
|
+ logExternalFailure("YIDA_FORM_INSTANCE_QUERY", requestedFormId, requestedFormInstanceId, exception);
|
|
|
+ throw exception;
|
|
|
+ }
|
|
|
+ Map<?, ?> result = resultOf(instanceDetail);
|
|
|
+ validateFormUuid(result, requestedFormId, requestedFormInstanceId);
|
|
|
|
|
|
- List<?> components = asList(result.get("formComponentValues"));
|
|
|
+ List<?> components = toFormComponents(result);
|
|
|
if (components.isEmpty()) {
|
|
|
- throw new IllegalArgumentException("Approval instance " + instanceId + " has no form component values");
|
|
|
+ throw new IllegalArgumentException("Yida form instance " + requestedFormInstanceId + " has no form data; "
|
|
|
+ + describeYidaResult(instanceDetail, result));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mapping != null) {
|
|
|
+ MingleiPortRequest request = toT100Request(requestedFormId, components, mapping);
|
|
|
+ LOGGER.info("Submitting supplier price approval from formId={} formInstanceId={} processInstanceId={} documentNo={} detailCount={}",
|
|
|
+ requestedFormId, requestedFormInstanceId, processInstanceId,
|
|
|
+ request.getDocumentNumber(), request.getDetailCount());
|
|
|
+ try {
|
|
|
+ Map<String, Object> t100Response = mingleiPortService.submitSupplierPriceApproval(request);
|
|
|
+ writeBackT100DocumentNumber(requestedFormId, requestedFormInstanceId,
|
|
|
+ requestedProcessInstanceId, t100Response);
|
|
|
+ return t100Response;
|
|
|
+ } catch (RestClientException exception) {
|
|
|
+ logExternalFailure("T100_DOCUMENT_PUSH", requestedFormId, requestedFormInstanceId, exception);
|
|
|
+ throw exception;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> parameter = toAdditionalT100Parameter(requestedFormId, components);
|
|
|
+ LOGGER.info("Submitting T100 document from formId={} formInstanceId={} processInstanceId={} dataKeyType={}",
|
|
|
+ requestedFormId, requestedFormInstanceId, processInstanceId, dataKeyType);
|
|
|
+ try {
|
|
|
+ return mingleiPortService.submitT100Document(parameter, dataKeyType);
|
|
|
+ } catch (RestClientException exception) {
|
|
|
+ logExternalFailure("T100_DOCUMENT_PUSH", requestedFormId, requestedFormInstanceId, exception);
|
|
|
+ throw exception;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * T100 成功生成单号后,将单号写回发起推送的宜搭流程实例。
|
|
|
+ * 回写只提交目标字段,避免覆盖流程中原有的其他表单数据。
|
|
|
+ */
|
|
|
+ private void writeBackT100DocumentNumber(String formId, String formInstanceId, String processInstanceId,
|
|
|
+ Map<String, Object> t100Response) {
|
|
|
+ if (!isT100Success(t100Response)) {
|
|
|
+ LOGGER.info("Skipping Yida document number write-back because T100 was not successful formId={} processInstanceId={}",
|
|
|
+ formId, processInstanceId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String documentNumber = requireText(extractT100DocumentNumber(t100Response),
|
|
|
+ "T100 successful response does not contain content.payload.std_data.parameter.pmdidocno");
|
|
|
+ String fieldId = T100_DOCUMENT_NUMBER_WRITE_BACK_FIELDS.get(formId);
|
|
|
+ if (fieldId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> updateFormData = new LinkedHashMap<String, Object>();
|
|
|
+ updateFormData.put(fieldId, documentNumber);
|
|
|
+ Map<String, Object> updateBody = new LinkedHashMap<String, Object>();
|
|
|
+ updateBody.put("appType", requireText(coordinationOfficeConfiguration.getAppType(),
|
|
|
+ "YIDA_COORDINATION_OFFICE_APP_TYPE is not configured"));
|
|
|
+ updateBody.put("systemToken", requireText(coordinationOfficeConfiguration.getSystemToken(),
|
|
|
+ "YIDA_COORDINATION_OFFICE_SYSTEM_TOKEN is not configured"));
|
|
|
+ updateBody.put("formUuid", formId);
|
|
|
+ updateBody.put("formInstanceId", formInstanceId);
|
|
|
+ updateBody.put("processInstanceId", processInstanceId);
|
|
|
+ updateBody.put("updateFormDataJson", toJson(updateFormData, "Yida process update data"));
|
|
|
+
|
|
|
+ LOGGER.info("Writing back T100 document number to Yida formId={} processInstanceId={} fieldId={}",
|
|
|
+ formId, processInstanceId, fieldId);
|
|
|
+ DDR_New updateResponse = yidaProcessOpenApiClient.updateProcessInstance(updateBody);
|
|
|
+ if (updateResponse == null || !updateResponse.isSuccess()) {
|
|
|
+ String code = updateResponse == null ? "EMPTY_RESPONSE" : defaultText(updateResponse.getCode(), "UNKNOWN");
|
|
|
+ String message = updateResponse == null ? "Yida process update response is empty"
|
|
|
+ : defaultText(updateResponse.getMessage(), "Yida process update failed");
|
|
|
+ LOGGER.error("Yida document number write-back was rejected formId={} processInstanceId={} fieldId={} code={} message={}",
|
|
|
+ formId, processInstanceId, fieldId, code, message);
|
|
|
+ throw new McException("YIDA_PROCESS_INSTANCE_UPDATE_FAILED", "Yida process update failed ["
|
|
|
+ + code + "]: " + message);
|
|
|
+ }
|
|
|
+ LOGGER.info("Yida document number write-back completed formId={} processInstanceId={} fieldId={}",
|
|
|
+ formId, processInstanceId, fieldId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isT100Success(Map<String, Object> response) {
|
|
|
+ if (response == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Object success = response.get("success");
|
|
|
+ if (success != null) {
|
|
|
+ return Boolean.TRUE.equals(success) || "true".equalsIgnoreCase(String.valueOf(success));
|
|
|
+ }
|
|
|
+ Map<?, ?> execution = t100Execution(response);
|
|
|
+ return execution != null && "0".equals(textValue(execution.get("code")));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String extractT100DocumentNumber(Map<String, Object> response) {
|
|
|
+ Map<?, ?> payload = t100Payload(response);
|
|
|
+ Map<?, ?> standardData = payload == null ? null : asMap(payload.get("std_data"));
|
|
|
+ Map<?, ?> parameter = standardData == null ? null : asMap(standardData.get("parameter"));
|
|
|
+ return parameter == null ? null : textValue(parameter.get("pmdidocno"));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 兼容接口网关包装后的 content.payload 与 T100 直返的 payload 两种响应格式。
|
|
|
+ */
|
|
|
+ private Map<?, ?> t100Payload(Map<String, Object> response) {
|
|
|
+ Map<?, ?> content = asMap(response.get("content"));
|
|
|
+ if (content != null) {
|
|
|
+ Map<?, ?> payload = asMap(content.get("payload"));
|
|
|
+ if (payload != null) {
|
|
|
+ return payload;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return asMap(response.get("payload"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<?, ?> t100Execution(Map<String, Object> response) {
|
|
|
+ Map<?, ?> payload = t100Payload(response);
|
|
|
+ Map<?, ?> standardData = payload == null ? null : asMap(payload.get("std_data"));
|
|
|
+ return standardData == null ? null : asMap(standardData.get("execution"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String toJson(Map<String, Object> value, String fieldName) {
|
|
|
+ try {
|
|
|
+ return objectMapper.writeValueAsString(value);
|
|
|
+ } catch (JsonProcessingException exception) {
|
|
|
+ throw new IllegalStateException(fieldName + " serialization failed", exception);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 仅记录外部调用所在阶段与安全元信息,避免输出宜搭表单或 T100 单据正文。
|
|
|
+ */
|
|
|
+ private void logExternalFailure(String stage, String formId, String processInstanceId,
|
|
|
+ RestClientException exception) {
|
|
|
+ LOGGER.error("Supplier price approval external call failed stage={} formId={} processInstanceId={} "
|
|
|
+ + "exceptionType={}",
|
|
|
+ stage, formId, processInstanceId, exception.getClass().getSimpleName());
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<?, ?> resultOf(Map<?, ?> instanceDetail) {
|
|
|
+ Map<?, ?> nestedResult = asMap(instanceDetail.get("result"));
|
|
|
+ // 部分宜搭响应会保留空 result,并将流程数据直接放在顶层。
|
|
|
+ return nestedResult == null || nestedResult.isEmpty() ? instanceDetail : nestedResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<?> toFormComponents(Map<?, ?> result) {
|
|
|
+ List<?> components = asList(result.get("formComponentValues"));
|
|
|
+ if (!components.isEmpty()) {
|
|
|
+ return components;
|
|
|
+ }
|
|
|
+ Map<?, ?> formData = findFormData(result, 4);
|
|
|
+ if (formData == null || formData.isEmpty()) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> convertedComponents = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Map.Entry<?, ?> entry : formData.entrySet()) {
|
|
|
+ if (!(entry.getKey() instanceof String)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Map<String, Object> component = new LinkedHashMap<String, Object>();
|
|
|
+ component.put("fieldId", entry.getKey());
|
|
|
+ component.put("value", entry.getValue());
|
|
|
+ convertedComponents.add(component);
|
|
|
+ }
|
|
|
+ return convertedComponents;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从宜搭流程详情的包装节点中定位表单字段。不同宜搭版本会在 result、data 或 formData
|
|
|
+ * 中重复包装,且表单字段可能以 JSON 字符串返回。
|
|
|
+ *
|
|
|
+ * @param value 当前待解析节点
|
|
|
+ * @param remainingDepth 允许继续展开的包装层级
|
|
|
+ * @return 表单字段 Map;未找到时返回 null
|
|
|
+ */
|
|
|
+ private Map<?, ?> findFormData(Object value, int remainingDepth) {
|
|
|
+ Object parsedValue = parseStructuredValue(value, "Yida process form data");
|
|
|
+ Map<?, ?> map = asMap(parsedValue);
|
|
|
+ if (map == null || map.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (containsYidaFieldId(map)) {
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ if (remainingDepth <= 0) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ for (String wrapperKey : Arrays.asList("formData", "data", "result", "content")) {
|
|
|
+ Object nestedValue = map.get(wrapperKey);
|
|
|
+ if (nestedValue == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Map<?, ?> nestedFormData = findFormData(nestedValue, remainingDepth - 1);
|
|
|
+ if (nestedFormData != null) {
|
|
|
+ return nestedFormData;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean containsYidaFieldId(Map<?, ?> values) {
|
|
|
+ for (Object key : values.keySet()) {
|
|
|
+ if (!(key instanceof String)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String fieldId = (String) key;
|
|
|
+ if (fieldId.startsWith("textField_") || fieldId.startsWith("numberField_")
|
|
|
+ || fieldId.startsWith("selectField_") || fieldId.startsWith("dateField_")
|
|
|
+ || fieldId.startsWith("tableField_") || fieldId.startsWith("associationFormField_")
|
|
|
+ || fieldId.startsWith("employeeField_") || fieldId.startsWith("serialNumberField_")
|
|
|
+ || fieldId.startsWith("departmentSelectField_")) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String describeYidaResult(Map<?, ?> instanceDetail, Map<?, ?> result) {
|
|
|
+ Object data = result.get("data");
|
|
|
+ Object nestedResult = instanceDetail.get("result");
|
|
|
+ Map<?, ?> nestedResultMap = asMap(nestedResult);
|
|
|
+ return "responseKeys=" + instanceDetail.keySet()
|
|
|
+ + ", resultType=" + (nestedResult == null ? "null" : nestedResult.getClass().getSimpleName())
|
|
|
+ + ", resultKeys=" + (nestedResultMap == null ? "[]" : nestedResultMap.keySet())
|
|
|
+ + ", dataType=" + (data == null ? "null" : data.getClass().getSimpleName());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将三类非供应商价格审批表单转换为各自定义的 T100 parameter 结构。
|
|
|
+ */
|
|
|
+ private Map<String, Object> toAdditionalT100Parameter(String formId, List<?> components) {
|
|
|
+ if (PACKAGING_MATERIAL_PRICE_APPROVAL_FORM_ID.equals(formId)) {
|
|
|
+ return toPackagingMaterialPriceApprovalParameter(components);
|
|
|
+ }
|
|
|
+ if (SUPPLIER_SUSPEND_EXIT_FORM_ID.equals(formId)) {
|
|
|
+ return toSupplierSuspendExitParameter(components);
|
|
|
+ }
|
|
|
+ if (PACKAGING_MATERIAL_ITEM_LIST_FORM_ID.equals(formId)) {
|
|
|
+ return toPackagingMaterialItemListParameter(components);
|
|
|
+ }
|
|
|
+ throw new IllegalArgumentException("Unsupported T100 document formId: " + formId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> toPackagingMaterialPriceApprovalParameter(List<?> components) {
|
|
|
+ String enterpriseName = requiredComponentText(components, "textField_mviyetxy", "textField_mviyetxy");
|
|
|
+ Map<String, Object> head = new LinkedHashMap<String, Object>();
|
|
|
+ head.put("pmaaucent", toT100EnterpriseCode(enterpriseName));
|
|
|
+ head.put("detail", toPackagingMaterialPriceApprovalDetails(components));
|
|
|
+
|
|
|
+ Map<String, Object> parameter = new LinkedHashMap<String, Object>();
|
|
|
+ parameter.put("head", head);
|
|
|
+ return parameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ //包材材质核价
|
|
|
+ private List<Map<String, Object>> toPackagingMaterialPriceApprovalDetails(List<?> components) {
|
|
|
+ Map<?, ?> tableComponent = requireComponent(components, "tableField_mt1av9od", "tableField_mt1av9od");
|
|
|
+ List<?> sourceRows = extractTableRows(tableComponent);
|
|
|
+ List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Object sourceRow : sourceRows) {
|
|
|
+ Map<?, ?> row = requireRow(sourceRow, "tableField_mt1av9od");
|
|
|
+ Map<String, Object> detail = new LinkedHashMap<String, Object>();
|
|
|
+ detail.put("pmaauc015", optionalRowNumber(row, "numberField_mt1av9oh"));
|
|
|
+ detail.put("pmaauc001", optionalRowText(row, "selectField_mviy59mp"));
|
|
|
+ details.add(detail);
|
|
|
}
|
|
|
+ return details;
|
|
|
+ }
|
|
|
|
|
|
- MingleiPortRequest request = toT100Request(components, mapping);
|
|
|
- LOGGER.info("Submitting supplier price approval from formId={} processInstanceId={} documentNo={} detailCount={}",
|
|
|
- requestedFormId, instanceId, request.getDocumentNumber(), request.getDetailCount());
|
|
|
- return mingleiPortService.submitSupplierPriceApproval(request);
|
|
|
+ /**
|
|
|
+ * 供应商暂停或恢复时,T100 的表头和明细使用相同的状态、供应商与企业代码;企业据点仅在明细传递。
|
|
|
+ */
|
|
|
+ private Map<String, Object> toSupplierSuspendExitParameter(List<?> components) {
|
|
|
+ String status = toT100SupplierStatus(
|
|
|
+ requiredComponentText(components, "selectField_mt82p09c", "selectField_mt82p09c"));
|
|
|
+ String supplierCode = requiredComponentText(components, "textField_mvgepmw0", "textField_mvgepmw0");
|
|
|
+ String enterpriseName = requiredComponentText(components, "textField_mvewj97z", "textField_mvewj97z");
|
|
|
+ String enterpriseCode = toT100EnterpriseCode(enterpriseName);
|
|
|
+ String enterpriseSite = requiredComponentText(components, "textField_mvewj980", "textField_mvewj980");
|
|
|
+
|
|
|
+ Map<String, Object> head = new LinkedHashMap<String, Object>();
|
|
|
+ head.put("pmaa083", status);
|
|
|
+ head.put("pmaa001", supplierCode);
|
|
|
+ head.put("pmaaent", enterpriseCode);
|
|
|
+
|
|
|
+ Map<String, Object> detail = new LinkedHashMap<String, Object>();
|
|
|
+ detail.put("pmab074", status);
|
|
|
+ detail.put("pmab001", supplierCode);
|
|
|
+ detail.put("pmabent", enterpriseCode);
|
|
|
+ detail.put("pmabsite", enterpriseSite);
|
|
|
+
|
|
|
+ Map<String, Object> parameter = new LinkedHashMap<String, Object>();
|
|
|
+ parameter.put("head", head);
|
|
|
+ parameter.put("detail", detail);
|
|
|
+ return parameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 宜搭保存企业名称,T100 的企业字段只接受对应的企业编码。
|
|
|
+ */
|
|
|
+ private String toT100EnterpriseCode(String enterpriseName) {
|
|
|
+ return "明磊".equals(enterpriseName) ? "87" : "60";
|
|
|
}
|
|
|
|
|
|
- private MingleiPortRequest toT100Request(List<?> components, SupplierPriceApprovalFormMapping mapping) {
|
|
|
+ /**
|
|
|
+ * T100 使用数字标记供应商状态,避免将宜搭选项文本直接写入状态字段。
|
|
|
+ */
|
|
|
+ private String toT100SupplierStatus(String status) {
|
|
|
+ if ("正常供应商".equals(status)) {
|
|
|
+ return "1";
|
|
|
+ }
|
|
|
+ if ("停用".equals(status)) {
|
|
|
+ return "0";
|
|
|
+ }
|
|
|
+ throw new IllegalArgumentException("Unsupported supplier status: " + status);
|
|
|
+ }
|
|
|
+
|
|
|
+ //包材料号维护清单维护审核流程
|
|
|
+ private Map<String, Object> toPackagingMaterialItemListParameter(List<?> components) {
|
|
|
+ String enterpriseSite = requiredComponentText(components, "selectField_msy2rh6q", "selectField_msy2rh6q");
|
|
|
+ String enterpriseCode = toT100EnterpriseCode(enterpriseSite);
|
|
|
+ Map<?, ?> tableComponent = requireComponent(components, "tableField_msh186sv", "tableField_msh186sv");
|
|
|
+ List<?> sourceRows = extractTableRows(tableComponent);
|
|
|
+ List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
|
|
|
+ for (Object sourceRow : sourceRows) {
|
|
|
+ Map<?, ?> row = requireRow(sourceRow, "tableField_msh186sv");
|
|
|
+ Map<String, Object> detail = new LinkedHashMap<String, Object>();
|
|
|
+ detail.put("pmabuc001", optionalRowText(row, "textField_mvix39fn"));
|
|
|
+ detail.put("pmabuc002", optionalRowText(row, "textField_mvix39fm"));
|
|
|
+ detail.put("pmabuc024", optionalRowNumber(row, "numberField_mvjb17mf"));
|
|
|
+ detail.put("pmabuc005", optionalRowText(row, "selectField_mv6etsnu"));
|
|
|
+ detail.put("pmabuc023", optionalRowText(row, "selectField_msy2rh6z"));
|
|
|
+ detail.put("pmabuc025", optionalRowNumber(row, "numberField_msy2rh7a"));
|
|
|
+ detail.put("pmabuc026", optionalRowText(row, "textField_msy2rh7c"));
|
|
|
+ detail.put("pmabuc027", optionalRowNumber(row, "numberField_msy2rh73"));
|
|
|
+ detail.put("pmabuc028", optionalRowNumber(row, "numberField_msy2rh74"));
|
|
|
+ detail.put("pmabuc029", optionalRowText(row, "textField_msy2rh76"));
|
|
|
+ detail.put("pmabuc030", optionalRowText(row, "textField_msy2rh77"));
|
|
|
+ detail.put("pmabuc031", optionalRowText(row, "textField_msy2rh78"));
|
|
|
+ detail.put("pmabuc032", optionalRowNumber(row, "numberField_msy2rh75"));
|
|
|
+ detail.put("pmabucent", enterpriseCode);
|
|
|
+ detail.put("pmabucsite", "ML");
|
|
|
+ detail.put("pmabucstus", "Y");
|
|
|
+ details.add(detail);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> head = new LinkedHashMap<String, Object>();
|
|
|
+ head.put("detail", details);
|
|
|
+ Map<String, Object> parameter = new LinkedHashMap<String, Object>();
|
|
|
+ parameter.put("head", head);
|
|
|
+ return parameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ private MingleiPortRequest toT100Request(String formId, List<?> components,
|
|
|
+ SupplierPriceApprovalFormMapping mapping) {
|
|
|
Map<String, Object> head = new LinkedHashMap<String, Object>();
|
|
|
head.put("pmdidocno", requiredComponentText(components, mapping.documentNoFieldId, "单据编号"));
|
|
|
- head.put("pmdi001", requiredComponentText(components, mapping.outsourceFieldId, "委外否"));
|
|
|
+ head.put("pmdi001", toT100YesNo(
|
|
|
+ requiredComponentText(components, mapping.outsourceFieldId, "委外否"), "委外否"));
|
|
|
head.put("pmdi034", requiredComponentText(components, mapping.integrationDocumentNoFieldId, "单号"));
|
|
|
head.put("pmdidocdt", requiredDateComponentText(components, mapping.quotationDateFieldId, "报价单日期"));
|
|
|
head.put("pmdi004", requiredComponentText(components, mapping.supplierFieldId, "核价供应商"));
|
|
|
head.put("pmdi015", requiredDateComponentText(components, mapping.effectiveDateFieldId, "生效日期"));
|
|
|
head.put("pmdi016", requiredDateComponentText(components, mapping.expiryDateFieldId, "失效日期"));
|
|
|
head.put("pmdi003", requiredComponentText(components, mapping.departmentFieldId, "使用部门"));
|
|
|
- head.put("pmdi002", requiredComponentText(components, mapping.applicantFieldId, "申请人"));
|
|
|
- head.put("pmdiud001", DEFAULT_ESTIMATED_FLAG);
|
|
|
+ head.put("pmdi002", resolveApplicantEmployeeNo(components, mapping.applicantFieldId));
|
|
|
+ head.put("pmdiud001", isEstimatedSupplierPriceApproval(formId) ? "Y" : "N");
|
|
|
head.put("pmdistus", DEFAULT_DOCUMENT_STATUS);
|
|
|
|
|
|
Map<String, Object> requestBody = new LinkedHashMap<String, Object>();
|
|
|
@@ -153,17 +547,53 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
return objectMapper.convertValue(requestBody, MingleiPortRequest.class);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 宜搭成员字段返回人员数组,T100 申请人字段需要花名册中的员工工号。
|
|
|
+ */
|
|
|
+ private String resolveApplicantEmployeeNo(List<?> components, String applicantFieldId) {
|
|
|
+ String applicantName = requiredComponentText(components, applicantFieldId, "申请人");
|
|
|
+ EmployeeRosterInfo employee = employeeRosterService.findByUsername(applicantName);
|
|
|
+ if (employee == null) {
|
|
|
+ throw new IllegalArgumentException("Applicant employee not found in roster: " + applicantName);
|
|
|
+ }
|
|
|
+ return requireText(employee.getEmployeeNo(), "Applicant employee has no employee_no in roster: " + applicantName);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将宜搭的是否字段转换为 T100 所需的 Y/N 标识,同时兼容历史表单已保存的 Y/N 值。
|
|
|
+ */
|
|
|
+ private String toT100YesNo(String value, String fieldName) {
|
|
|
+ if ("是".equals(value) || "Y".equalsIgnoreCase(value)) {
|
|
|
+ return "Y";
|
|
|
+ }
|
|
|
+ if ("否".equals(value) || "N".equalsIgnoreCase(value)) {
|
|
|
+ return "N";
|
|
|
+ }
|
|
|
+ throw new IllegalArgumentException(fieldName + " must be 是 or 否");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 暂估类供应商价格审批单需要向 T100 标记为暂估,核价类表单保持非暂估。
|
|
|
+ */
|
|
|
+ private boolean isEstimatedSupplierPriceApproval(String formId) {
|
|
|
+ return ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID.equals(formId)
|
|
|
+ || SUBSIDIARY_ESTIMATED_SUPPLIER_PRICE_APPROVAL_FORM_ID.equals(formId);
|
|
|
+ }
|
|
|
+
|
|
|
private List<Map<String, Object>> toT100Details(List<?> components, SupplierPriceApprovalFormMapping mapping) {
|
|
|
Map<?, ?> tableComponent = requireComponent(components, mapping.detailTableFieldId, "核价明细");
|
|
|
List<?> sourceRows = extractTableRows(tableComponent);
|
|
|
List<Map<String, Object>> details = new ArrayList<Map<String, Object>>();
|
|
|
- for (Object sourceRow : sourceRows) {
|
|
|
+ for (int index = 0; index < sourceRows.size(); index++) {
|
|
|
+ Object sourceRow = sourceRows.get(index);
|
|
|
Map<?, ?> row = asMap(sourceRow);
|
|
|
if (row == null) {
|
|
|
throw new IllegalArgumentException("核价明细包含无法解析的行数据");
|
|
|
}
|
|
|
Map<String, Object> detail = new LinkedHashMap<String, Object>();
|
|
|
- detail.put("pmdj011", requiredRowText(row, mapping.detailPriceFieldId, "核价"));
|
|
|
+ detail.put("pmdj011", requiredRowText(row, mapping.detailPriceFieldId,
|
|
|
+ "核价 fieldId=" + mapping.detailPriceFieldId + ", row=" + (index + 1)
|
|
|
+ + ", availableFieldIds=" + row.keySet()));
|
|
|
detail.put("pmdj002", textValue(rowFieldValue(row, mapping.detailItemFieldId)));
|
|
|
detail.put("pmdj030", defaultText(textValue(rowFieldValue(row, mapping.detailRemarkFieldId)), ""));
|
|
|
details.add(detail);
|
|
|
@@ -225,6 +655,30 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
return requireText(textValue(rowFieldValue(row, fieldId)), fieldName + " must not be blank");
|
|
|
}
|
|
|
|
|
|
+ private Map<?, ?> requireRow(Object value, String fieldName) {
|
|
|
+ Map<?, ?> row = asMap(value);
|
|
|
+ if (row == null) {
|
|
|
+ throw new IllegalArgumentException(fieldName + " contains an invalid row");
|
|
|
+ }
|
|
|
+ return row;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String optionalRowText(Map<?, ?> row, String fieldId) {
|
|
|
+ return defaultText(textValue(rowFieldValue(row, fieldId)), "");
|
|
|
+ }
|
|
|
+
|
|
|
+ private Object optionalRowNumber(Map<?, ?> row, String fieldId) {
|
|
|
+ String value = optionalRowText(row, fieldId);
|
|
|
+ if (value.isEmpty()) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return new BigDecimal(value);
|
|
|
+ } catch (NumberFormatException ignored) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private Map<?, ?> requireComponent(List<?> components, String fieldId, String fieldName) {
|
|
|
Map<?, ?> component = findComponent(components, fieldId, fieldName);
|
|
|
if (component == null) {
|
|
|
@@ -233,6 +687,24 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
return component;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 仅在字段缺失时返回实例中的字段标识,便于定位表单版本或字段映射差异,且不暴露表单值。
|
|
|
+ */
|
|
|
+ private List<String> componentFieldIds(List<?> components) {
|
|
|
+ List<String> fieldIds = new ArrayList<String>();
|
|
|
+ for (Object item : components) {
|
|
|
+ Map<?, ?> component = asMap(item);
|
|
|
+ if (component == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String fieldId = textValue(firstPresent(component, "fieldId", "id", "bizAlias"));
|
|
|
+ if (fieldId != null) {
|
|
|
+ fieldIds.add(fieldId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fieldIds;
|
|
|
+ }
|
|
|
+
|
|
|
private Map<?, ?> findComponent(List<?> components, String fieldId, String fieldName) {
|
|
|
for (Object item : components) {
|
|
|
Map<?, ?> component = asMap(item);
|
|
|
@@ -267,7 +739,7 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
}
|
|
|
|
|
|
private String textValue(Object value) {
|
|
|
- Object parsedValue = parseStructuredValue(value, "字段");
|
|
|
+ Object parsedValue = parseTextValue(value);
|
|
|
if (parsedValue == null) {
|
|
|
return null;
|
|
|
}
|
|
|
@@ -296,6 +768,25 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
return text.trim().isEmpty() ? null : text.trim();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 宜搭普通字段可能是 JSON 字符串,也可能只是恰好以 {@code [} 或 {@code \{} 开头的文本。
|
|
|
+ * 前者解析为结构化值,后者保留原文,避免普通字段阻断整张单据推送。
|
|
|
+ */
|
|
|
+ private Object parseTextValue(Object value) {
|
|
|
+ if (!(value instanceof String)) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ String text = ((String) value).trim();
|
|
|
+ if (!(text.startsWith("{") || text.startsWith("["))) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return objectMapper.readValue(text, Object.class);
|
|
|
+ } catch (JsonProcessingException ignored) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void validateFormUuid(Map<?, ?> result, String requestedFormId, String instanceId) {
|
|
|
String formUuid = textValue(firstPresent(result, "formUuid", "modelUuid"));
|
|
|
if (formUuid != null && !requestedFormId.equals(formUuid)) {
|
|
|
@@ -303,12 +794,17 @@ public class SupplierPriceApprovalProcessServiceImpl implements SupplierPriceApp
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private SupplierPriceApprovalFormMapping resolveFormMapping(String formId) {
|
|
|
- SupplierPriceApprovalFormMapping mapping = FORM_MAPPINGS.get(formId);
|
|
|
- if (mapping == null) {
|
|
|
- throw new IllegalArgumentException("Unsupported supplier price approval formId: " + formId);
|
|
|
+ private String resolveDataKeyType(String formId) {
|
|
|
+ if (PACKAGING_MATERIAL_PRICE_APPROVAL_FORM_ID.equals(formId)) {
|
|
|
+ return PACKAGING_MATERIAL_PRICE_APPROVAL_TYPE;
|
|
|
+ }
|
|
|
+ if (SUPPLIER_SUSPEND_EXIT_FORM_ID.equals(formId)) {
|
|
|
+ return SUPPLIER_SUSPEND_EXIT_TYPE;
|
|
|
}
|
|
|
- return mapping;
|
|
|
+ if (PACKAGING_MATERIAL_ITEM_LIST_FORM_ID.equals(formId)) {
|
|
|
+ return PACKAGING_MATERIAL_ITEM_LIST_TYPE;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
private Map<?, ?> requireMap(Object value, String message) {
|