Compare commits

...

3 Commits

Author SHA1 Message Date
mzr 4bd070516b 消息接口 2025-07-03 10:36:49 +08:00
mzr 91ce065bdf 物料新增修改后同步艾普MES的物料、流程生产订单审批后推送艾普MES 2025-07-03 10:35:42 +08:00
mzr d918f9afb3 工具类 2025-07-03 10:35:39 +08:00
5 changed files with 392 additions and 5 deletions

View File

@ -0,0 +1,184 @@
package nc.bs.mmpac.pmo.pac0002.bp.rule;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.logging.Log;
import nc.bs.logging.Logger;
import nc.bs.uapbd.util.MyHelper;
import nc.bs.uapbd.util.ThirdPartyPostRequestUtil;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.itf.arap.goldentax.SysParaInitQuery;
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.scmpub.util.ArrayUtil;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
* 流程生产订单审批后推送艾普MES
*
* @author mzr
* @date 2025/7/3
*/
public class AfterApproveSyncEpicMesRule implements IRule<PMOAggVO> {
private static final String LOG_INFO_NAME = "OALOG";
private static final Log obmlog = Log.getInstance(LOG_INFO_NAME);
private static final String MES_PMO_SYNC_URL = "/prj-v5-web/ext/api/wrokOrder";
@Override
public void process(PMOAggVO[] pmoAggVOS) {
if (ArrayUtil.isEmpty(pmoAggVOS)) {
return;
}
try {
List<PMOAggVO> filteredOrders = checkAndFilterBillSrcOrg(pmoAggVOS);
if (filteredOrders.isEmpty()) {
obmlog.debug("没有符合条件的生产订单需要同步到MES系统。");
return;
}
obmlog.info("开始同步生产订单到MES系统符合条件的订单数量: " + filteredOrders.size());
// 推送到MES系统
JSONArray dataArr = new JSONArray();
for (PMOAggVO aggVO : filteredOrders) {
PMOHeadVO head = aggVO.getParentVO();
PMOItemVO[] bodys = aggVO.getChildrenVO();
if (bodys == null || bodys.length == 0) {
obmlog.warn("生产订单 " + head.getVbillcode() + " 没有行信息,跳过同步。");
continue;
}
JSONObject object = buildSyncData(aggVO);
dataArr.add(object);
}
JSONObject data = new JSONObject();
data.put("workOrders", dataArr);
pushData(data);
obmlog.info("生产订单同步到MES系统处理完成。");
} catch (Exception e) {
obmlog.error("同步生产订单到MES系统失败: " + e.getMessage(), e);
ExceptionUtils.wrappException(e);
}
}
/**
* 调用MES接口并处理特定错误
*
* @param param 请求体
* @throws BusinessException 如果发生非特定可忽略的错误
*/
private void pushData(JSONObject param) throws BusinessException {
String responseString = null;
try {
String baseUrl = SysParaInitQuery.getParaString("GLOBLE00000000000000", "EPICMESURL");
String requestUrl = baseUrl + MES_PMO_SYNC_URL;
responseString = ThirdPartyPostRequestUtil.sendPostRequest(requestUrl, param.toJSONString());
obmlog.info(" MES系统原始返回: " + responseString);
JSONObject jsonResponse = JSONObject.parseObject(responseString);
} catch (Exception e) {
obmlog.error(" 调用MES或处理响应时发生错误。原始响应: " + responseString + " 错误: " + e.getMessage(), e);
throw new BusinessException("调用MES或处理响应时发生错误" + e.getMessage(), e);
}
}
/**
* 检查并筛选需要同步的单据
*/
private List<PMOAggVO> checkAndFilterBillSrcOrg(PMOAggVO[] pmoAggVOS) throws BusinessException {
List<PMOAggVO> aggvoList = new ArrayList<>();
for (PMOAggVO aggVo : pmoAggVOS) {
String pkOrg = aggVo.getParentVO().getPk_org();
String orgCode = MyHelper.transferField(FactoryVO.getDefaultTableName(), FactoryVO.CODE, FactoryVO.PK_FACTORY, pkOrg);
// 检查当前组织是否为电力电子
if (MyHelper.checkIfDldzOrg(orgCode)) {
aggvoList.add(aggVo);
}
}
return aggvoList;
}
/**
* 组装数据
*/
private JSONObject buildSyncData(PMOAggVO aggVO) {
PMOHeadVO headVo = aggVO.getParentVO();
PMOItemVO[] pmoItems = aggVO.getChildrenVO();
JSONObject data = new JSONObject();
// {
// "workOrders": [
// {
// "id": null, // 唯一标识主键
// "siteCode": "04", // 工厂编码
// "contractNo": "HDDK0111325", // 合同号
// "workOrderCode": "DSF01-2501230028",// 工单号
// "qty": "1.000", // 计划数量字符串类型
// "produCode": "103248250005", // 产品编码
// "produName": "150KV滤抗-特高压宝塔山(试装)-低端", // 产品名称
// "bomCode": "103248250005", // BOM 编码
// "planBeginDate": 1751328000000, // 计划开始时间毫秒级时间戳
// "planEndDate": 1751328000000, // 计划结束时间毫秒级时间戳
// "endDate": 1751328000000, // 试验结束时间毫秒级时间戳
// "type": null, // 类型I:新增 U:修改 D:删除
// "auditCode": "Y", // 审核码Y:已审核 N:未审核
// "contractName": "特高压宝塔山±800 千伏换流站工程", // 合同名称
// "transferPlanTime": "2025-07-01", // 生产转检计划时间格式YYYY-MM-DD
// "receiptScheduledTime": "2025-07-01", // 完工入库时间格式YYYY-MM-DD
// "companyCode": "DLDZ", // 公司编码
// "companyName": "泰开电力电子" // 公司名称
// }
// ],
// "mrls": [
// {
// "workOrderCode": "DSF01-2501230028",// 工单号
// "mrlCode": "2305050447", // 物料编码
// "mrlName": "铝加工件", // 物料名称
// "qty": 1.000, // 数量浮点数
// "unit": "" // 单位
// }
// ]
// }
return data;
}
/**
* 转换特殊字段 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;
}
}

7
uapbd/META-INF/msg.rest Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding='gb2312'?>
<module>
<rest>
<resource classname="nccloud.api.uapbd.msg.MsgResource" exinfo=""/>
</rest>
</module>

View File

@ -0,0 +1,110 @@
package nccloud.api.uapbd.material.listener;
import com.alibaba.fastjson.JSONObject;
import nc.bs.bd.baseservice.ArrayClassConvertUtil;
import nc.bs.businessevent.IBusinessEvent;
import nc.bs.businessevent.IBusinessListener;
import nc.bs.businessevent.bd.BDCommonEvent;
import nc.bs.logging.Logger;
import nc.bs.uapbd.util.MyHelper;
import nc.bs.uapbd.util.ThirdPartyPostRequestUtil;
import nc.itf.arap.goldentax.SysParaInitQuery;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.material.marbasclass.MarBasClassVO;
import nc.vo.bd.material.measdoc.MeasdocVO;
import nc.vo.org.FactoryVO;
import nc.vo.pub.BusinessException;
import java.util.HashMap;
import java.util.Map;
/**
* 物料新增修改后同步艾普MES的物料
*
* @author mzr
* @date 2025/06/27
*/
public class MaterialToEpicMesListener implements IBusinessListener {
private static final String reqUrl = "/prj-v5-web/ext/api/mrl";
@Override
public void doAction(IBusinessEvent event) throws BusinessException {
BDCommonEvent e = (BDCommonEvent) event;
String eventType = event.getEventType();
Object[] objs = e.getObjs();
MaterialVO[] useVOs = ArrayClassConvertUtil.convert(objs, MaterialVO.class);
// EventType是事件编码
if ("1002".equals(eventType)) {
// 新增后
buildSyncData(useVOs, eventType);
} else if ("1004".equals(eventType)) {
// 修改后
buildSyncData(useVOs, eventType);
}
}
/**
* 构建同步数据
*/
private void buildSyncData(MaterialVO[] useVOs, String eventType) throws BusinessException {
for (MaterialVO vo : useVOs) {
// 判断物料的业务单元是否是电力电子公司不是则跳过
String pkOrg = vo.getPk_org();
String orgCode = MyHelper.transferField(FactoryVO.getDefaultTableName(), FactoryVO.CODE, FactoryVO.PK_FACTORY, pkOrg);
if (!MyHelper.checkIfDldzOrg(orgCode)) {
continue;
}
// 1=未启用;2=已启用;3=已停用;
Integer enablestate = vo.getEnablestate();
String statusCode = (3 == enablestate) ? "N" : "Y";
JSONObject singleObj = new JSONObject();
singleObj.put("id", null);// 唯一标识主键
singleObj.put("siteCode", null);// 工厂编码
singleObj.put("mrlCode", vo.getCode());// 物料编码
singleObj.put("mrlName", vo.getName());// 物料名称
String pkMeasdoc = vo.getPk_measdoc();
String unitName = MyHelper.transferField(MeasdocVO.getDefaultTableName(), MeasdocVO.NAME, MeasdocVO.PK_MEASDOC, pkMeasdoc);
singleObj.put("unit", unitName);// 单位
singleObj.put("model", vo.getMaterialtype());// 型号
singleObj.put("specification", vo.getMaterialspec());// 规格
singleObj.put("type", getType(eventType));// 类型I:新增 U:修改 D:删除
singleObj.put("deputyUnit", null);// 副单位
singleObj.put("auditCode", "1");// 审核码
singleObj.put("statusCode", statusCode);// 状态码Y表示启用N表示停用
singleObj.put("mrlTypeErp", "1");// 物料类型ERP1:专用件3:通用件
String pk_marbasclass = vo.getPk_marbasclass();
String mrlTypeCOde = MyHelper.transferField(MarBasClassVO.getDefaultTableName(), MarBasClassVO.CODE, MarBasClassVO.PK_MARBASCLASS, pk_marbasclass);
singleObj.put("mrlType", mrlTypeCOde);// 物料分类编码
singleObj.put("convertRate", "1");// 单位换算率
singleObj.put("isCheck", "1");// 是否选中1:0:
pushData(singleObj);
}
}
/**
* 推送同步数据
*/
private void pushData(JSONObject param) throws BusinessException {
String baseUrl = SysParaInitQuery.getParaString("GLOBLE00000000000000", "EPICMESURL");
String requestUrl = baseUrl + reqUrl;
String result = ThirdPartyPostRequestUtil.sendPostRequest(requestUrl, param.toJSONString());
JSONObject resultObj = JSONObject.parseObject(result);
Logger.error("EpicMes-Material-req = " + result);
if ("false".equals(resultObj.getString("success"))) {
throw new BusinessException("EpicMes-Material-failerror:" + resultObj.getString("msg"));
} else {
Logger.error("EpicMes-Material-suc,result[" + resultObj.toJSONString() + "]");
}
}
private String getType(String eventType) {
// 类型I:新增 U:修改 D:删除
Map<String, String> map = new HashMap<>();
map.put("1002", "I");
map.put("1004", "U");
return map.getOrDefault(eventType, "I");
}
}

View File

@ -0,0 +1,85 @@
package nc.bs.uapbd.util;
import nc.bs.dao.BaseDAO;
import nc.bs.logging.Logger;
import nc.itf.arap.goldentax.SysParaInitQuery;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.vo.cmp.util.StringUtils;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 工具类
*
* @author mzr
* @date 2025/7/3
*/
public class MyHelper {
private static final BaseDAO dao = new BaseDAO();
/**
* 根据主键查询编码
*/
public static String transferField(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();
}
/**
* 检查当前组织是否为电力电子
*/
public static boolean checkIfDldzOrg(String code) throws BusinessException {
String targetCode = SysParaInitQuery.getParaString("GLOBLE00000000000000", "DLDZORG");
if (targetCode == null || nc.vo.am.common.util.StringUtils.isEmpty(targetCode)) {
throw new BusinessException("未配置组织参数,请前往 [业务参数设置-全局] 配置DLDZORG参数");
}
String[] orgItem = targetCode.split(";");
for (String orgCode : orgItem) {
if (!orgCode.isEmpty() && orgCode.equals(code)) {
Logger.debug("当前处理组织校验为电力电子:" + code);
return true;
}
}
return false;
}
/**
* 转换特殊字段 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;
}
}

View File

@ -3,15 +3,15 @@ package nccloud.api.uapbd.msg;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.DAOException;
import nc.bs.logging.Logger;
import nc.bs.pub.pf.PfMessageUtil;
import nc.bs.trade.business.HYSuperDMO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.msg.CommonMessageVO;
import nc.vo.pub.msg.UserNameObject;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.sm.UserVO;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.baseapp.core.log.NCCForUAPLogger;
import nccloud.bs.pub.pf.PfMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.ws.rest.resource.AbstractNCCRestResource;
import org.json.JSONString;
@ -57,7 +57,7 @@ public class MsgResource extends AbstractNCCRestResource {
String roleId = (String) jsonObject.get("roleId");
try {
// 通知消息字段最大为4000位
if (content.length() > 1500) {
if (content != null && content.length() > 1500) {
content = content.substring(0, 1500);
}
@ -111,17 +111,18 @@ public class MsgResource extends AbstractNCCRestResource {
return null;
}
String strWhere = " dr = 0 AND cuserid in (" +
"select cuserid from sm_user_role where pk_role = [roleId] and (disabledate is null or disabledate >= [now]) " +
"select cuserid from sm_user_role where pk_role = '[roleId]' and (disabledate is null or disabledate >= '[now]') " +
")";
strWhere = strWhere.replace("[roleId]", roleId);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
strWhere = strWhere.replace("[now]", time);
NCCForUAPLogger.debug("time = " + time);
// NCCForUAPLogger.debug("time = " + time);
try {
vos = (UserVO[]) getSuperDMO().queryByWhereClause(UserVO.class, strWhere);
} catch (DAOException e) {
Logger.error("MsgResource-getUserByRole-exp:" + e.getMessage());
ExceptionUtils.wrappBusinessException(e.getMessage());
}
return vos;