diff --git a/ic/src/private/nccloud/pubift/commen/impl/utils/HttpPostOtherSysImpl.java b/ic/src/private/nccloud/pubift/commen/impl/utils/HttpPostOtherSysImpl.java index 988ff9b..16417c0 100644 --- a/ic/src/private/nccloud/pubift/commen/impl/utils/HttpPostOtherSysImpl.java +++ b/ic/src/private/nccloud/pubift/commen/impl/utils/HttpPostOtherSysImpl.java @@ -62,13 +62,38 @@ public class HttpPostOtherSysImpl implements IHttpPostOtherSys { obmlog.debug("三方接口返回::" + jsonResponse.toJSONString()); // 记录三方接口返回的数据 - String success = jsonResponse.getString("Success"); // 获取返回结果中的Success字段 - if ("false".equals(success)) { // 判断请求是否成功 - String errorMessage = jsonResponse.getString("ErrorMessage"); // 获取错误信息 - if (errorMessage == null) { - errorMessage = "外部系统未提供错误消息。"; + // 检查是否存在 "Data" 数组 + if (jsonResponse.containsKey("Data") && jsonResponse.get("Data") instanceof com.alibaba.fastjson.JSONArray) { + com.alibaba.fastjson.JSONArray dataArray = jsonResponse.getJSONArray("Data"); + for (int i = 0; i < dataArray.size(); i++) { + JSONObject dataObject = dataArray.getJSONObject(i); + String successInData = dataObject.getString("Success"); + if ("false".equalsIgnoreCase(successInData)) { + String errorMessage = dataObject.getString("ErrorMessage"); + if (errorMessage == null || errorMessage.isEmpty()) { + errorMessage = dataObject.getString("Message"); // 尝试获取 Message 字段 + } + if (errorMessage == null || errorMessage.isEmpty()) { + errorMessage = "外部系统未提供错误消息。"; + } + throw new BusinessException("同步mes系统失败,错误消息:" + errorMessage); + } + } + // 如果Data数组中所有项都成功,则认为整体成功 + // 当前逻辑:如果Data数组存在且所有项成功,则不再检查顶层Success,直接认为成功。 + } else { + // 原有的逻辑,处理顶层Success字段 + String success = jsonResponse.getString("Success"); // 获取返回结果中的Success字段 + if ("false".equalsIgnoreCase(success)) { // 判断请求是否成功 + String errorMessage = jsonResponse.getString("ErrorMessage"); // 获取错误信息 + if (errorMessage == null || errorMessage.isEmpty()) { + errorMessage = jsonResponse.getString("Message"); // 尝试获取 Message 字段 + } + if (errorMessage == null || errorMessage.isEmpty()) { + errorMessage = "外部系统未提供错误消息。"; + } + throw new BusinessException("同步mes系统失败,错误消息:" + errorMessage); // 抛出业务异常 } - throw new BusinessException("同步mes系统失败,错误消息:" + errorMessage); // 抛出业务异常 } } catch (BusinessException e) { diff --git a/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/PMOApproveBP.java b/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/PMOApproveBP.java index 943304d..e8de6d8 100644 --- a/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/PMOApproveBP.java +++ b/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/PMOApproveBP.java @@ -1,5 +1,7 @@ package nc.bs.mmpac.pmo.pac0002.bp; + +import nc.bs.mmpac.pmo.pac0002.bp.rule.AfterApproveRuleSyncMes; import nc.bs.mmpac.pmo.pac0002.bp.rule.AfterApprovingSynchronizeRuleRZ; import nc.bs.mmpac.pmo.pac0002.pluginpoint.PMOPluginPoint; import nc.bs.mmpac.pmo.pac0002.rule.*; @@ -51,6 +53,9 @@ public class PMOApproveBP { processer.addAfterRule(auditSupplyRule); // 审批后推送到RZ系统 processer.addAfterRule(new AfterApprovingSynchronizeRuleRZ()); + // 审批后推送流程生产订单到MES + processer.addAfterRule(new AfterApproveRuleSyncMes()); + } public PMOAggVO[] approveCancel(PMOAggVO[] fullBills, PMOAggVO[] originBills) { diff --git a/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/rule/AfterApproveRuleSyncMes.java b/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/rule/AfterApproveRuleSyncMes.java new file mode 100644 index 0000000..35ec8dd --- /dev/null +++ b/mmpac/src/private/nc/bs/mmpac/pmo/pac0002/bp/rule/AfterApproveRuleSyncMes.java @@ -0,0 +1,284 @@ +package nc.bs.mmpac.pmo.pac0002.bp.rule; + + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import nc.bs.dao.BaseDAO; +import nc.bs.framework.common.NCLocator; +import nc.bs.logging.Log; +import nc.impl.pubapp.pattern.rule.IRule; +import nc.jdbc.framework.processor.ColumnProcessor; +import nc.vo.bd.bom.bom0202.entity.BomVO; +import nc.vo.bd.material.MaterialVersionVO; +import nc.vo.cmp.util.StringUtils; +import nc.vo.mmpac.pmo.pac0002.entity.PMOAggVO; +import nc.vo.mmpac.pmo.pac0002.entity.PMOHeadVO; +import nc.vo.mmpac.pmo.pac0002.entity.PMOItemVO; +import nc.vo.org.FactoryVO; +import nc.vo.pub.BusinessException; +import nc.vo.pubapp.pattern.exception.ExceptionUtils; +import nc.vo.pubapp.pattern.pub.SqlBuilder; +import nc.vo.scmpub.util.ArrayUtil; +import nc.vo.vorg.DeptVersionVO; +import nccloud.pubift.commen.itf.utils.IHttpPostOtherSys; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * 流程生产订单审批后推送MES + */ +public class AfterApproveRuleSyncMes implements IRule { + + public static final IHttpPostOtherSys HTTP_POST_OTHER_SYS = NCLocator.getInstance().lookup(IHttpPostOtherSys.class); + + private static final String LOG_INFO_NAME = "OALOG"; + + private static final Log obmlog = Log.getInstance(LOG_INFO_NAME); + + private static final BaseDAO dao = new BaseDAO(); + + private static final String MES_PMO_SYNC_URL = "/GTHINKING/AjaxService/N_SCSJJSA/102525006.ashx/receive_woinfo_insert"; + + @Override + public void process(PMOAggVO[] pmoAggVOS) { + if (ArrayUtil.isEmpty(pmoAggVOS)) { + return; + } + try { + // 检查并筛选生产订单 + List filteredOrders = checkAndFilterBillSrcOrg(pmoAggVOS); + if (filteredOrders.isEmpty()) { + obmlog.info("没有符合条件的生产订单需要同步到MES系统。"); + return; + } + + obmlog.info("开始同步生产订单到MES系统,符合条件的订单数量: " + filteredOrders.size()); + // 推送到MES系统 + for (PMOAggVO aggVO : filteredOrders) { + PMOHeadVO head = aggVO.getParentVO(); + PMOItemVO[] bodys = aggVO.getChildrenVO(); + + if (bodys == null || bodys.length == 0) { + obmlog.warn("生产订单 " + head.getVbillcode() + " 没有行信息,跳过同步。"); + continue; + } + + for (PMOItemVO item : bodys) { + syncOrderItemToMes(head, item); + } + } + obmlog.info("生产订单同步到MES系统处理完成。"); + + } catch (Exception e) { + obmlog.error("同步生产订单到MES系统失败: " + e.getMessage(), e); + ExceptionUtils.wrappException(e); + } + } + + /** + * 检查并筛选需要同步的单据 + */ + private List checkAndFilterBillSrcOrg(PMOAggVO[] pmoAggVOS) throws BusinessException { + List aggvoList = new ArrayList<>(); + for (PMOAggVO aggvo : pmoAggVOS) { + String pkOrg = aggvo.getParentVO().getPk_org(); + String orgCode = transferCodeByPk(FactoryVO.getDefaultTableName(), FactoryVO.CODE, FactoryVO.PK_FACTORY, pkOrg); + if ("C034".equals(orgCode)) { + aggvoList.add(aggvo); + } + } + return aggvoList; + } + + private void syncOrderItemToMes(PMOHeadVO head, PMOItemVO item) throws BusinessException { + JSONObject data = new JSONObject(); + String vbillcode = head.getVbillcode(); // 单据号 + String itemRow = item.getVrowno(); // 行号 + + obmlog.info("开始为生产订单 " + vbillcode + " 行 " + itemRow + " 构建同步MES数据。"); + + // orderNo String 是 生产订单号 vbillcode + if (vbillcode.length() > 18) { + throw new BusinessException("MES同步要求:生产订单 " + vbillcode + " 行 " + itemRow + " 单据号长度不能超过18位。"); + } + + data.put("orderNo", vbillcode); + + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + // startDate String 是 计划开工日期 格式yyyy-MM-dd tplanstarttime + if (item.getTplanstarttime() != null && item.getTplanstarttime().toStdString() != null) { + data.put("startDate", item.getTplanstarttime().getDate().toStdString().toString()); + } else { + data.put("startDate", null); + } + + // endDate String 是 计划完工日期 格式yyyy-MM-dd tplanendtime + if (item.getTplanendtime() != null && item.getTplanendtime().getDate().toStdString() != null) { + data.put("endDate", item.getTplanendtime().getDate().toStdString().toString()); + } else { + data.put("endDate", null); // Or handle as error if required + } + + // type String 是 类型 有传入销售订单号时传入MPS;否则传入EXT 默认:MPS + // status String 是 状态 有传入销售订单号时传入P;否则传入I 默认:P + // MRPMark String 是 MRP标志 有传入销售订单号时传入Y;否则传入N 默认:Y + data.put("type", "MPS"); + data.put("status", "P"); + data.put("MRPMark", "Y"); + + // materialId String 是 物料编码 cmaterialvid (物料版本PK) + if (!StringUtils.isEmpty(item.getCmaterialvid())) { + String materialCode = transferCodeByPk(MaterialVersionVO.getDefaultTableName(), MaterialVersionVO.CODE, MaterialVersionVO.PK_MATERIAL, item.getCmaterialvid()); + data.put("materialId", materialCode); + } else { + throw new BusinessException("生产订单 " + vbillcode + " 行 " + itemRow + " 物料版本信息获取失败。"); + } + + + // bomNum String 是 产品结构号 cbbomversionid (BOM版本PK) - + if (item.getCbomversionid() != null) { + String hcmaterialid = transferCodeByPk(BomVO.TABLE_NAME, BomVO.HCMATERIALID, nc.vo.bd.bom.bom0202.entity.BomVO.CBOMID, item.getCbomversionid()); + String bomNum = transferCodeByPk(MaterialVersionVO.getDefaultTableName(), MaterialVersionVO.CODE, MaterialVersionVO.PK_SOURCE, hcmaterialid); + data.put("bomNum", bomNum); + + // routeNum String 是 工艺路线号 vrtversion (工艺路线版本号)// 2025年5月23日9点50分,段京岗:routeNum和bomNum取相同值 + data.put("routeNum", bomNum); + + } + + // departmentId String 是 部门编码 cdeptvid (生产车间PK) + if (!StringUtils.isEmpty(item.getCdeptvid())) { + String deptCode = transferCodeByPk(DeptVersionVO.getDefaultTableName(), DeptVersionVO.CODE, DeptVersionVO.PK_VID, item.getCdeptvid()); + data.put("departmentId", deptCode); + } else { + throw new BusinessException("生产订单 " + vbillcode + " 行 :MES系统要求" + itemRow + " 部门信息不能为空。"); + } + + + // factoryId String 是 工厂编码 pk_org (库存组织PK) + if (!StringUtils.isEmpty(head.getPk_org())) { + String factoryCode = transferCodeByPk(FactoryVO.getDefaultTableName(), FactoryVO.CODE, FactoryVO.PK_FACTORY, head.getPk_org()); + data.put("factoryId", factoryCode); + } else { + throw new BusinessException("生产订单 " + vbillcode + " 行 : MES系统要求" + itemRow + " 工厂信息不能为空。"); + } + + // productNum String 制令号 vsalebillcode + data.put("productNum", item.getVsalebillcode()); + // saleOrderNo String 销售订单号 vsalebillcode + data.put("saleOrderNo", item.getVsalebillcode()); + + // saleSequenceNum Double 销售订单序号 vfirstrowno + if (!StringUtils.isEmpty(item.getVfirstrowno())) { + try { + data.put("saleSequenceNum", Double.parseDouble(item.getVfirstrowno())); + } catch (NumberFormatException e) { + obmlog.warn("生产订单 " + vbillcode + " 行 " + itemRow + "MES系统同步: 销售订单序号 (vfirstrowno) '" + item.getVfirstrowno() + "' 无法解析为小数。" + e.getMessage()); + data.put("saleSequenceNum", null); + } + } else { + data.put("saleSequenceNum", null); + } + + // 备注 + data.put("remark", item.getVnote()); + + + // quantity double 是 需求数量 nnum + data.put("quantity", item.getNnum() != null ? item.getNnum().doubleValue() : 0.0); + // assitQuantity double 辅助需求数量 nastnum + data.put("assitQuantity", item.getNastnum() != null ? item.getNastnum().doubleValue() : 0.0); + + // scaleFactor double 换算系数 vchangerate + data.put("scaleFactor", transferSpecialField(item.getVchangerate())); + + // method String 是 排产方式 N|排产时指定 S|顺排 D|倒排 默认:N + data.put("method", "N"); + // priority Double 排产优先级 默认:空 + data.put("priority", null); + + // compileDate String 编制日期 格式yyyy-MM-dd 默认传入当前日期 dbilldate + String compileDateStr; + if (head.getDbilldate() != null) { + compileDateStr = head.getDbilldate().toStdString(); + data.put("compileDate", compileDateStr); + } + + // 通过自定义属性传 + JSONArray properties = new JSONArray(); + JSONObject SXZF16 = new JSONObject(); + JSONObject SXZF17 = new JSONObject(); + JSONObject SXZF18 = new JSONObject(); + SXZF16.put("propertyFiled", item.getVparentbillcode()); + SXZF17.put("propertyFiled", item.getVparentmorowno()); + SXZF18.put("propertyFiled", head.getVtrantypecode()); + properties.add(SXZF16); + properties.add(SXZF17); + properties.add(SXZF18); + + data.put("properties", properties); + JSONObject requestPayload = new JSONObject(); + JSONArray dataArr = new JSONArray(); + dataArr.add(data); + requestPayload.put("data", dataArr); + + + obmlog.info("生产订单 " + vbillcode + " 行 " + itemRow + " 同步MES请求数据: " + requestPayload.toJSONString()); + + // Send to MES + // Note: The actual endpoint URL might need to be configured or obtained from a central place. + HTTP_POST_OTHER_SYS.sendToExternalSystem(MES_PMO_SYNC_URL, requestPayload); + obmlog.info("生产订单 " + vbillcode + " 行 " + itemRow + " 已成功发送到MES系统。"); + } + + /** + * 根据主键查询编码 + */ + private String transferCodeByPk(String tableName, String selectField, String pkField, String pk) throws BusinessException { + if (StringUtils.isEmpty(pk)) { + return null; + } + SqlBuilder sqlBuilder = new SqlBuilder(); + sqlBuilder.append(" select " + selectField); + sqlBuilder.append(" from " + tableName); + sqlBuilder.append(" where "); + sqlBuilder.append(pkField, pk); + Object o = dao.executeQuery(sqlBuilder.toString(), new ColumnProcessor()); + if (o == null) { + throw new BusinessException("未查询到编码信息,sql【" + sqlBuilder + "】"); + } + return o.toString(); + } + + /** + * 转换特殊字段 如 1/1 转换为小数 1.0 + */ + + private String transferSpecialField(String field) { + if (field == null || field.trim().isEmpty()) { + return null; + } + String[] split = field.split("/"); + if (split.length == 2) { + String numStr = split[0].trim(); + String denStr = split[1].trim(); + if (denStr.equals("0")) { + return "0.00"; // 分母不能为零 + } + try { + BigDecimal numerator = new BigDecimal(numStr); + BigDecimal denominator = new BigDecimal(denStr); + return numerator.divide(denominator, 2, RoundingMode.HALF_UP).toString(); + } catch (NumberFormatException e) { + return field; // 非法数字,返回原字段 + } + } + return field; + } + +}