feat(bom): 实现BOM同步失败后的错误处理机制

- 新增定时任务插件 BomToEpicMesPlugin 用于同步推送失败的BOM数据
- 在 BomSaveAfterEpicMesRule 中增加异常捕获与错误信息记录逻辑
This commit is contained in:
mzr 2025-10-07 12:39:13 +08:00
parent 111828326d
commit 4de8c5b102
2 changed files with 237 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import nc.bs.dao.BaseDAO;
import nc.bs.logging.Log;
import nc.bs.uapbd.util.MyHelper;
import nc.bs.uapbd.util.ThirdPartyPostRequestUtil;
@ -13,11 +14,14 @@ import nc.vo.bd.bom.bom0202.entity.AggBomVO;
import nc.vo.bd.bom.bom0202.entity.BomItemVO;
import nc.vo.bd.bom.bom0202.entity.BomVO;
import nc.vo.bd.material.MaterialVO;
import nc.vo.fi.pub.SqlUtils;
import nc.vo.org.OrgVO;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* BOM修改后同步艾普MES的BOM
@ -30,6 +34,14 @@ public class BomSaveAfterEpicMesRule implements IRule<AggBomVO> {
private static final Log logDl = Log.getInstance(LOG_INFO_NAME);
private static final String reqUrl = "/prj-v5-web/ext/api/bom";
private Map<String, String> configParams;
private BaseDAO dao;
public BaseDAO getDao() {
if (dao == null) {
dao = new BaseDAO();
}
return dao;
}
@Override
public void process(AggBomVO[] vos) {
@ -38,9 +50,11 @@ public class BomSaveAfterEpicMesRule implements IRule<AggBomVO> {
configParams = MyHelper.getConfigParams("Dldz-config", null);
JSONArray data = buildSyncData(vos);
if (!data.isEmpty()) {
pushData(data);
pushData(data, vos);
}
} catch (BusinessException e) {
logDl.error("EpicMes-BOM-exp:" + e.getMessage(), e);
handleSyncBomExp(vos, "N", e.getMessage());
ExceptionUtils.wrappException(e);
}
}
@ -112,7 +126,7 @@ public class BomSaveAfterEpicMesRule implements IRule<AggBomVO> {
/**
* 推送同步数据
*/
private void pushData(JSONArray param) throws BusinessException {
private void pushData(JSONArray param, AggBomVO[] vos) throws BusinessException {
// 转json字符串的时候保留null值
String jsonStr = JSON.toJSONString(param,
SerializerFeature.WriteMapNullValue,
@ -130,6 +144,34 @@ public class BomSaveAfterEpicMesRule implements IRule<AggBomVO> {
if (!"1".equals(resultObj.getString("flag"))) {
// throw new BusinessException("EpicMes-BOM-error:" + resultObj.getString("msg"));
logDl.error("EpicMes-BOM-error,result[" + resultObj.toJSONString() + "]");
// 保存BOM推送的错误信息
handleSyncBomExp(vos, "N", resultObj.getString("msg"));
} else {
handleSyncBomExp(vos, "Y", "");
}
}
/**
* 更新错误信息
*/
private void handleSyncBomExp(AggBomVO[] vos, String errorCode, String errorMsg) {
if (MMValueCheck.isEmpty(vos)) {
return;
}
Set<String> ids = new HashSet<>();
for (AggBomVO vo : vos) {
BomVO hvo = (BomVO) vo.getParentVO();
String cbomid = hvo.getCbomid();
ids.add(cbomid);
}
try {
String inSql = SqlUtils.getInStr("cbomid", ids.toArray(new String[0]), Boolean.TRUE);
String updateSql = "update bd_bom set hvdef19 = '[errorCode]' where " + inSql;
updateSql = updateSql.replace("[errorCode]", errorCode);
int updatedRows = getDao().executeUpdate(updateSql);
} catch (BusinessException e) {
logDl.error("EpicMes-BOM-updateErrorInfo = " + e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,193 @@
package nc.bs.uapbd.task.base;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Log;
import nc.bs.pub.pa.PreAlertObject;
import nc.bs.pub.taskcenter.BgWorkingContext;
import nc.bs.pub.taskcenter.IBackgroundWorkPlugin;
import nc.bs.uapbd.util.MyHelper;
import nc.bs.uapbd.util.ThirdPartyPostRequestUtil;
import nc.itf.bd.bom.bom0202.IBomBillQueryService;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.vo.bd.bom.bom0202.entity.AggBomVO;
import nc.vo.bd.bom.bom0202.entity.BomItemVO;
import nc.vo.bd.bom.bom0202.entity.BomVO;
import nc.vo.bd.material.MaterialVO;
import nc.vo.fi.pub.SqlUtils;
import nc.vo.org.OrgVO;
import nc.vo.pub.BusinessException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 定时同步推送失败的BOM到艾普MES
*
* @author mzr
* @date 20251006
*/
public class BomToEpicMesPlugin implements IBackgroundWorkPlugin {
private static final String LOG_INFO_NAME = "syscron";
private static final Log logDl = Log.getInstance(LOG_INFO_NAME);
private static final String reqUrl = "/prj-v5-web/ext/api/bom";
private Map<String, String> configParams;
private BaseDAO dao;
public BaseDAO getDao() {
if (dao == null) {
dao = new BaseDAO();
}
return dao;
}
@Override
public PreAlertObject executeTask(BgWorkingContext bgWorkingContext) throws BusinessException {
try {
String sql = " select * from v_bip_so_cron";
List<Map<String, String>> pkList = (List<Map<String, String>>) getDao().executeQuery(sql.toString(), new MapListProcessor());
if (pkList.isEmpty()) {
return null;
}
configParams = MyHelper.getConfigParams("Dldz-config", null);
if (configParams.isEmpty()) {
return null;
}
IBomBillQueryService qry = NCLocator.getInstance().lookup(IBomBillQueryService.class);
for (Map<String, String> map : pkList) {
String cbomid = map.get("cbomid");
AggBomVO[] vos = qry.queryAggBomByBomID(new String[]{cbomid});
JSONArray data = buildSyncData(vos);
if (!data.isEmpty()) {
pushData(data, vos);
}
}
} catch (Exception e) {
logDl.error("BomToEpicMesPlugin-exp:" + e.getMessage(), e);
}
return null;
}
/**
* 构建同步数据
*/
private JSONArray buildSyncData(AggBomVO[] useVOs) throws BusinessException {
JSONArray data = new JSONArray();
for (AggBomVO vo : useVOs) {
// 判断物料的业务单元是否是电力电子公司不是则跳过
BomVO hvo = (BomVO) vo.getParentVO();
String hvnote = hvo.getHvnote();
// 跳过期初的BOM
if ("202509QC".equals(hvnote)) {
continue;
}
String pkOrg = (String) hvo.getAttributeValue("pk_org");
String orgCode = MyHelper.transferField(OrgVO.getDefaultTableName(), OrgVO.CODE, OrgVO.PK_ORG, pkOrg);
if (MyHelper.checkIfDldzOrg(orgCode, configParams)) {
continue;
}
BomItemVO[] childrenVOs = vo.getChildrenVO();
if (MMValueCheck.isEmpty(childrenVOs)) {
continue;
}
// 只推送生产BOM 1=生产BOM;2=包装BOM;3=配置BOM;
Integer fbomtype = hvo.getFbomtype();
if (fbomtype != 1) {
continue;
}
String hcmaterialid = hvo.getHcmaterialid();// 父项物料编码
String hversion = hvo.getHversion();// BOM版本号
String mitm = MyHelper.getStrValByCondition(MaterialVO.getDefaultTableName(), MaterialVO.CODE,
MaterialVO.PK_MATERIAL + " = '" + hcmaterialid + "'");
for (BomItemVO childrenVO : childrenVOs) {
String cmaterialid = childrenVO.getCmaterialid();
String sitm = MyHelper.getStrValByCondition(MaterialVO.getDefaultTableName(), MaterialVO.CODE,
MaterialVO.PK_MATERIAL + " = '" + cmaterialid + "'");
// 组装数据
JSONObject singleObj = new JSONObject();
singleObj.put("mitm", mitm); // 制造物料编码(ERP父项物料编码)
singleObj.put("sitm", sitm); // 子物料编码
singleObj.put("orderNum", hversion); // 合同号(ERP中电力电子项目号=BOM版本号)
singleObj.put("qana", childrenVO.getNassitemnum().toString()); // 数量(ERP子项数量)
singleObj.put("ver", hversion); // BOM版本号
singleObj.put("remark", childrenVO.getVnote()); // 备注
data.add(singleObj);
}
/**
* [
* {
* "mitm": "DSF01-2501230028",
* "sitm": "2305050447",
* "orderNum": "111",
* "qana": 1,
* "ver": "1",
* "remark": ""
* }
* ]
*/
}
return data;
}
/**
* 推送同步数据
*/
private void pushData(JSONArray param, AggBomVO[] vos) throws BusinessException {
// 转json字符串的时候保留null值
String jsonStr = JSON.toJSONString(param,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty
);
logDl.error("EpicMes-BOM-param = " + jsonStr);
// NCCForUAPLogger.debug("EpicMes-BOM-param = " + jsonStr);
String baseUrl = configParams.get("epicMesUrl");
String requestUrl = baseUrl + reqUrl;
logDl.error("EpicMes-BOM-url = " + requestUrl);
String result = ThirdPartyPostRequestUtil.sendPostRequest(requestUrl, jsonStr);
JSONObject resultObj = JSONObject.parseObject(result);
logDl.error("EpicMes-BOM-res = " + result);
// NCCForUAPLogger.debug("EpicMes-BOM-result = " + result);
if (!"1".equals(resultObj.getString("flag"))) {
// throw new BusinessException("EpicMes-BOM-error:" + resultObj.getString("msg"));
logDl.error("EpicMes-BOM-error,result[" + resultObj.toJSONString() + "]");
// 保存BOM推送的错误信息
// handleSyncBomExp(vos, "N", resultObj.getString("msg"));
} else {
handleSyncBomExp(vos, "Y", "");
}
}
/**
* 更新错误信息
*/
private void handleSyncBomExp(AggBomVO[] vos, String errorCode, String errorMsg) {
if (MMValueCheck.isEmpty(vos)) {
return;
}
Set<String> ids = new HashSet<>();
for (AggBomVO vo : vos) {
BomVO hvo = (BomVO) vo.getParentVO();
String cbomid = hvo.getCbomid();
ids.add(cbomid);
}
try {
String inSql = SqlUtils.getInStr("cbomid", ids.toArray(new String[0]), Boolean.TRUE);
String updateSql = "update bd_bom set hvdef19 = '[errorCode]' where " + inSql;
updateSql = updateSql.replace("[errorCode]", errorCode);
int updatedRows = getDao().executeUpdate(updateSql);
} catch (BusinessException e) {
logDl.error("EpicMes-BOM-updateErrorInfo = " + e.getMessage(), e);
}
}
}