This commit is contained in:
lihao 2025-10-27 19:52:18 +08:00
parent 215c55e889
commit 09fe9de4ee
3 changed files with 959 additions and 0 deletions

View File

@ -0,0 +1,253 @@
package nccloud.web.pu.arrival.action;
import nc.itf.pu.m23.qc.IArriveForQC;
import nc.pubitf.pu.m23.pubquery.IArrivePubQuery;
import nc.pubitf.qc.c001.pu.ReturnObjectFor23;
import nc.vo.pu.m23.entity.ArriveHeaderVO;
import nc.vo.pu.m23.entity.ArriveItemVO;
import nc.vo.pu.m23.entity.ArriveVO;
import nc.vo.pu.m23.entity.ArriveViewVO;
import nc.vo.pu.pub.util.AggVOUtil;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.model.entity.view.AbstractDataView;
import nc.vo.pubapp.pattern.model.tool.BillComposite;
import nc.vo.qc.pub.enumeration.StrictLevelEnum;
import nccloud.commons.lang.ArrayUtils;
import nccloud.dto.pu.puinvoice.entity.DataInfo;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.core.json.IJson;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.json.JsonFactory;
import nccloud.framework.web.processor.template.GridConvertProcessor;
import nccloud.pubitf.pu.arrival.service.IArrivalQueryService;
import nccloud.web.pu.arrivalqc.entity.QualityCheckInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @description 检验
* @author ligangt
* @date 2018年8月28日 下午1:43:35
* @version ncc1.0
*/
public class QualityCheckAction implements ICommonAction {
@Override
public Object doAction(IRequest request) {
try {
// 获取前台json
IJson json = JsonFactory.create();
QualityCheckInfo info = json.fromJson(request.read(),
QualityCheckInfo.class);
ArriveViewVO[] views = null;
if (info.isQcEnable()) {
DataInfo[] idTs = info.getIdTs();
views = queryViewVOs(idTs);
} else {
GridConvertProcessor processor = new GridConvertProcessor();
views = processor.fromGrid(info.getGrid());
}
if (views != null && views.length > 0) {
// IPubUtilService pubService = ServiceLocator
// .find(IPubUtilService.class);
// if (pubService.isOrgQcEnable(info.getPk_org())) {
// 非紧急放行入库数量>0,即根据质检入库
// ArriveItemVO item = views[0].getBVO();
// if
// (MathTool.compareTo(MathTool.sub(item.getNaccumstorenum(),
// item.getNaccumletgoinnum()), UFDouble.ZERO_DBL) > 0) {
// //ExceptionUtils.wrapBusinessException("紧急放行数量大于入库数量");
// return false;
// }
// }
ArriveVO[] vos = this.getArriveVOs(views);
for (ArriveVO vo : vos) {
ArriveItemVO[] bvos = vo.getBVO();
for (ArriveItemVO bvo : bvos) {
UFDouble nchecknum = bvo.getNchecknum();
UFDouble nwillelignum = bvo.getNwillelignum();
if (nchecknum != null && nwillelignum != null) {
if (nchecknum.compareTo(UFDouble.ZERO_DBL) < 0
|| nwillelignum.compareTo(UFDouble.ZERO_DBL) < 0) {
ExceptionUtils.wrapBusinessException(
nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID(
"4004100_0", "04004100-0010")/*
* @res "报检数量和合格主数量不允许为负数"
*/);
}
}
UFDouble naccumchecknum = bvo.getNaccumchecknum();
if (naccumchecknum != null) {
if (naccumchecknum.compareTo(bvo.getNnum()) == 0) {
UFDouble naccumstorenum = bvo.getNaccumstorenum();
if (naccumstorenum != null
&& naccumstorenum.compareTo(UFDouble.ZERO_DBL) > 0) {
// ExceptionUtils.wrapBusinessException(
// nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
// .getStrByID("4004100_0", "04004100-0012")
// /* @res "第" */ + bvo.getCrowno()
// + nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
// .getStrByID("4004100_0",
// "04004100-0307")/* @res 04004100-0062 "行已经完全入库,不能生成报检单"
// NCC-362748 修改后行已经生成过报检单且正在检验中不允许复检*/);
ExceptionUtils.wrapBusinessException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4008015_0",
"04008015-0077"+"\n", null, new String[] {
bvo.getCrowno()
}));
/* @res 04004100-0062 "行已经完全入库,不能生成报检单"
NCC-362748 修改后{0}行已经生成过报检单且正在检验中不允许复检*/
}
}
}
}
}
ArriveVO[] returnVos = this.check(vos, info.isCheck());
if (null == returnVos) {
ExceptionUtils.wrapBusinessException(
nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("4004100_0",
"04004100-0011")/* @res "到货单检验失败!" */);
}
ServiceLocator.find(IArriveForQC.class).pushWmsByArriveVOs(vos);
// 把后台返回的轻量级聚合VO转换为视图VO
// new ClientBillCombinServer<ArriveVO>().combine(vos,
// returnVos);
// ArriveViewVO[] newViews = ArrivePublicUtil
// .convertAggToViewVO(vos);
// grid = processor.convert(info.getGrid().getPageid(),
// newViews);
// String[] successIds = this.getSuccessBIDs(returnVos);
// return successIds;
}
} catch (Exception e) {
ExceptionUtils.wrapException(e);
}
return null;
}
private ArriveViewVO[] queryViewVOs(DataInfo[] idTs) {
List<String> bids = new ArrayList<String>();
Map<String, String> idTsIndex = new HashMap<String, String>();
for (DataInfo item : idTs) {
bids.add(item.getId());
idTsIndex.put(item.getId(), item.getTs());
}
IArrivalQueryService qryService = ServiceLocator
.find(IArrivalQueryService.class);
ArriveViewVO[] viewvos = qryService
.queryViewByBIDs(bids.toArray(new String[0]));
// 重设ts
for (ArriveViewVO viewvo : viewvos) {
viewvo.setAttributeValue("ts",
idTsIndex.get(viewvo.getPk_arriveorder_b()));
}
return viewvos;
}
// private String[] getSuccessBIDs(ArriveVO[] returnVos) {
// List<String> bid_l = new ArrayList<String>();
// for (ArriveVO arrivevo : returnVos) {
// ArriveItemVO[] itemvos = arrivevo.getBVO();
// for (ArriveItemVO item : itemvos) {
// bid_l.add(item.getPk_arriveorder_b());
// }
// }
// return bid_l.toArray(new String[0]);
// }
private ArriveVO[] getArriveVOs(ArriveViewVO[] views) {
List<ArriveHeaderVO> headers = new ArrayList<ArriveHeaderVO>();
List<ArriveItemVO> items = new ArrayList<ArriveItemVO>();
for (AbstractDataView view : views) {
headers.add((ArriveHeaderVO) view.getVO(ArriveHeaderVO.class));
items.add((ArriveItemVO) view.getVO(ArriveItemVO.class));
}
BillComposite<ArriveVO> bc = new BillComposite<ArriveVO>(ArriveVO.class);
ArriveVO tempVO = new ArriveVO();
bc.append(tempVO.getMetaData().getParent(),
headers.toArray(new ArriveHeaderVO[headers.size()]));
bc.append(tempVO.getMetaData().getVOMeta(ArriveItemVO.class),
items.toArray(new ArriveItemVO[items.size()]));
return bc.composite();
}
/**
* 调用后台接口进行检验
*
* @param vos
* 到货单vo
* @param isCheck
* @return 检验结果数组
* @throws Exception
*/
private ArriveVO[] check(ArriveVO[] vos, boolean isCheck) throws Exception {
Object[] objs = ServiceLocator.find(IArriveForQC.class).qualityCheck(vos,
isCheck);
ArriveVO[] result = (ArriveVO[]) objs[0];
ReturnObjectFor23 rof = (ReturnObjectFor23) objs[1];
// 得到质检模块的提示信息
if (rof != null) {
Map<String, Integer> strictMap = rof.getCsourcebid_strictlevel();
Set<String> keySet = strictMap.keySet();
IArrivePubQuery arriveQuery = ServiceLocator.find(IArrivePubQuery.class);
ArriveItemVO[] items = arriveQuery
.queryItemVOByBids(keySet.toArray(new String[keySet.size()]));
String[] bpks = AggVOUtil.getPrimaryKeys(items);
if (strictMap.size() > 0) {
for (Map.Entry<String, Integer> entry : strictMap.entrySet()) {
String itempk = entry.getKey();
int dji = entry.getValue().intValue();
if (StrictLevelEnum.FREE.getReturnType() == dji) {
int i = Arrays.binarySearch(bpks, itempk);
items[i].getCrowno();
ExceptionUtils.wrapBusinessException(
nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
.getStrByID("4004100_0", "04004100-0012")/* @res "第" */
+ items[i].getCrowno()
+ nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID(
"4004100_0",
"04004100-0013")/*
* @res "行为质检连续批的严格程度为免检,不需要生成报检单!"
*/);
} else if (StrictLevelEnum.PAUSE.getReturnType() == dji) {
int i = Arrays.binarySearch(bpks, itempk);
items[i].getCrowno();
ExceptionUtils.wrapBusinessException(
nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
.getStrByID("4004100_0", "04004100-0012")/* @res "第" */
+ items[i].getCrowno()
+ nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID(
"4004100_0",
"04004100-0014")/*
* @res "行为质检连续批的严格程度为暂停, 不能生成报检单!"
*/);/*
* { 0 } 行为质检连续批的严格程度为暂停
* 不能生成报检单
*/
}
}
}
}
if (!ArrayUtils.isEmpty(result)) {
return result;
}
return null;
}
}

View File

@ -0,0 +1,649 @@
package nc.impl.pu.m23.qc;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Log;
import nc.impl.pu.m23.qc.action.AntiQualityCheckAction;
import nc.impl.pu.m23.qc.action.QualityCheckAction;
import nc.impl.pubapp.bd.material.assistant.MarAssistantCheckUtils;
import nc.impl.pubapp.pattern.data.vo.VOQuery;
import nc.impl.pubapp.pattern.data.vo.VOUpdate;
import nc.itf.arap.goldentax.SysParaInitQuery;
import nc.itf.pu.m23.qc.IArriveForQC;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.ResultSetProcessor;
import nc.pubitf.uapbd.IMaterialPubService_C;
import nc.vo.am.common.util.StringUtils;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.stordoc.StordocVO;
import nc.vo.org.OrgQueryUtil;
import nc.vo.org.OrgVO;
import nc.vo.pu.m23.entity.ArriveHeaderVO;
import nc.vo.pu.m23.entity.ArriveItemVO;
import nc.vo.pu.m23.entity.ArriveVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.qc.c001.entity.ApplyHeaderVO;
import nc.vo.qc.c001.entity.ApplySourceItemVO;
import nc.vo.qc.c001.entity.ApplyVO;
import nccloud.api.uapbd.wms.utils.WmsSyncUtils;
import nccloud.pubitf.scmpub.pub.service.ISCMPubQueryService;
import java.util.*;
/**
* <p>
* <b>本类主要完成以下功能</b>
* <ul>
* <li>到货单的质检
* <li>到货单的反检
* </ul>
* <p>
* <p>
*
* @author hanbin
* @version 6.0
* @time 2010-9-28 下午01:26:15
* @since 6.0
*/
public class ArriveForQCImpl implements IArriveForQC {
private static final Log log = Log.getInstance("wmslog");
private final WmsSyncUtils wmsSyncUtils = new WmsSyncUtils();
private static final BaseDAO dao = new BaseDAO();
@Override
public ArriveItemVO[] antiQualityCheck(ArriveItemVO[] bills) throws BusinessException {
try {
AntiQualityCheckAction action = new AntiQualityCheckAction();
return action.antiQualityCheck(bills);
} catch (Exception ex) {
ExceptionUtils.marsh(ex);
}
return null;
}
@Override
public Object[] qualityCheck(ArriveVO[] bills, boolean isCheck)
throws BusinessException {
try {
QualityCheckAction action = new QualityCheckAction();
return action.qualityCheck(bills, isCheck);
} catch (Exception ex) {
ExceptionUtils.marsh(ex);
}
return null;
}
@Override
public ApplyVO[] pushWmsByArriveVOs(ArriveVO[] bills) throws Exception {
//检查到货单组织是否全是成套
log.error("到货单检验推送wms--检查组织是否为WMSORG里参数开始");
boolean isWmsCt = checkOrgBeyondSysParam(bills);
log.error("到货单检验推送wms--检查组织是否为WMSORG里参数结束");
if(!isWmsCt){
log.error("到货单检验推送wms--检查组织不为WMSORG里参数结束推送");
return null;
}
String wmsBJPKS = InvocationInfoProxy.getInstance().getProperty("wmsBJPKS");
if (wmsBJPKS == null || wmsBJPKS.length() < 1) {
throw new BusinessException("发送WMS数据未查询到报检单pk或已存在下游报检单请检查");
}
log.error("到货单检验推送wms--到货单推送生成报检单主键字符串【"+wmsBJPKS+"");
String[] pks = wmsBJPKS.split("_");
if (pks == null || pks.length < 1) {
throw new BusinessException("解析报检单pk失败请检查");
}
//根据表头主键查询报检单
ApplyVO[] applyVOs = (ApplyVO[]) ((ISCMPubQueryService) NCLocator.getInstance().lookup(ISCMPubQueryService.class)).billquery(ApplyVO.class, pks);
this.pushWms(applyVOs);
InvocationInfoProxy.getInstance().setProperty("wmsBJPKS", null);
return applyVOs;
}
private boolean checkOrgBeyondSysParam(ArriveVO[] bills) throws BusinessException {
String targetCode = SysParaInitQuery.getParaString("GLOBLE00000000000000", "WMSORG");
if (targetCode == null || StringUtils.isEmpty(targetCode)) {
throw new BusinessException("未配置组织参数,请前往 [业务参数设置-全局] 配置WMSORG 参数");
}
String[] orgItem = targetCode.split(";");
if(orgItem==null || orgItem.length<1){
throw new BusinessException("WMSORG全局参数解析失败请检查");
}
//使用Stream将orgItem转成list
List<String> orgList = Arrays.asList(orgItem);
Set<String> orgPKs=new HashSet<>();
for(ArriveVO arriveVO: bills){
String pkOrg = arriveVO.getHVO().getPk_org();
orgPKs.add(pkOrg);
}
OrgVO[] orgVOS = OrgQueryUtil.queryOrgVOByPks(orgPKs.toArray(new String[0]));
if(orgVOS==null || orgVOS.length<1){
throw new BusinessException("未查询到组织信息,请检查");
}
boolean containCT=false;
boolean containOther=false;
for(OrgVO orgVO:orgVOS){
if(orgList.contains(orgVO.getCode())){
containCT=true;
}else{
containOther=true;
}
}
if(containCT && containOther){
throw new BusinessException("存在非【"+targetCode+"】组织数据与其一起检验,请检查");
}
return containCT;
}
private void pushWms(ApplyVO[] applyVOs) throws BusinessException {
try {
JSONObject wmsData = new JSONObject();
// 构造表头数据
JSONArray jsonArray = new JSONArray();
//2025年10月17日09点19分--过滤虚拟仓
List<ApplyVO> filterData = new ArrayList<>();
for (ApplyVO applyVO : applyVOs) {
this.checkInfo(applyVO);
ApplyHeaderVO headVO = applyVO.getHVO();
String vbillcode = headVO.getVbillcode();
// 检查是否为虚拟仓
String isVirtual = wmsSyncUtils.transferFieldByPkAllowNull(StordocVO.getDefaultTableName(),
"def1", StordocVO.PK_STORDOC,
headVO.getPk_stordoc());
if ("Y".equals(isVirtual)) {
log.error("ArriveForQCImpl -到货单检验,生成的报检单【"+vbillcode+"】 仓库[" + headVO.getPk_stordoc() + "]为虚拟仓,跳过同步");
continue;
}
filterData.add(applyVO);
//2025年10月17日09点19分--过滤虚拟仓
}
if(filterData.isEmpty()){
log.error("ArriveForQCImpl -到货单检验筛选完之后无可同步报检单结束WMS同步");
return;
}
ApplyVO[] syncApplyVOs=filterData.toArray(new ApplyVO[0]);
this.constructWMSData(jsonArray, syncApplyVOs);
if (jsonArray == null || jsonArray.isEmpty()) {
throw new BusinessException("当前报检单号同步数据为空,不同步WMS");
}
wmsData.put("header", jsonArray);
String method = "TK_BIP_QC_ORDER";
//同步前更新上游和本单--失败回滚成功落库
log.error("回写报检单Vdef3开始--接口失败回滚,接口成功落库");
// 标记同步成功
List<ApplyHeaderVO> headvos = new ArrayList<>();
for (ApplyVO applyVO : syncApplyVOs) {
applyVO.getHVO().setVdef3("Y");
applyVO.getHVO().setStatus(1);
headvos.add(applyVO.getHVO());
}
VOUpdate<ApplyHeaderVO> applyVOUpdater = new VOUpdate<>();
applyVOUpdater.update(headvos.toArray(new ApplyHeaderVO[0]), new String[]{"vdef3"});
log.error("回写报检单Vdef结束--接口失败回滚,接口成功落库");
// 回写上游到货单成功
handleUpstreamArriveOrderSuccess(syncApplyVOs);
// 后规则最后一个 更新
log.error("开始同步报检单到WMS");
// log.error("同步报文【" + wmsData.toJSONString() + "");
wmsSyncUtils.sendToExternalSystem(method, wmsData);
log.error("报检单同步WMS成功");
} catch (Exception e) {
log.error("检验结束同步WMS失败" + e.getMessage());
throw new BusinessException("同步WMS失败" + e.getMessage());
}
}
private void constructWMSData(JSONArray jsonArray, ApplyVO[] applyVOs) throws Exception {
//获取时间戳
long timestamp = System.currentTimeMillis();
for (ApplyVO applyVO : applyVOs) {
ApplyHeaderVO headVO = applyVO.getHVO();
String vbillcode = headVO.getVbillcode();
log.error("到货单检验推送wms--到货单推送生成报检单单号【"+vbillcode+"");
ApplySourceItemVO[] itemVOs = applyVO.getB2VO();
ApplySourceItemVO itemExampleVO = itemVOs[0];
JSONObject headData = new JSONObject();
// Map<String, Object> headData = new HashMap<>();
// 构建仓库ID: "CK" + 组织编码 + "001"
String orgCode = wmsSyncUtils.transferCodeByPk("org_stockorg", "code", "pk_stockorg",
headVO.getPk_stockorg());
String warehouseId = "CK" + (orgCode != null ? orgCode : "") + "001";
headData.put("organizationId", "TK"); // 组织 默认TK
headData.put("warehouseId", warehouseId); // 仓库ID必填
// headData.put("customerId", "TKJT"); // 货主必填默认值
//2025年9月3日10点37分--货主改为和仓库编码一致 --sdlizheng start
headData.put("customerId", warehouseId);
//2025年9月3日10点37分--货主改为和仓库编码一致 --sdlizheng end
// 根据表体源头单据类型编码确定订单类型
String asnType = getAsnTypeByFirstTypeCode(itemVOs);
if (asnType == null) {
throw new BusinessException("报检单号【" + vbillcode + "】 - 未知的源头单据类型编码,不同步此报检单");
}
headData.put("asnType", asnType); // 订单类型必填根据源头单据类型编码确定
headData.put("QCNO", headVO.getVbillcode()); // 质检单号必填
//2025年9月2日09点01分--表头添加到货日期--sdlizheng start
headData.put("BIP_TIME", headVO.getDapplydate().toString());
//2025年9月2日09点01分--表头添加到货日期--sdlizheng end
headData.put("MSG_BATCH", String.valueOf( timestamp));
headData.put("QCSTATUS", "00"); // 质检单状态必填默认00
// 到货单号取来源单据号
headData.put("SOURCEORDERNO1", itemExampleVO.getVsourcecode() != null ? itemExampleVO.getVsourcecode() : ""); // 到货单号必填
headData.put("qty_rejected", headVO.getNnum() != null ? headVO.getNnum().toString() : ""); // 报检数量必填
headData.put("supplierId", wmsSyncUtils.transferCodeByPk("bd_supplier", "code", "pk_supplier", headVO.getPk_supplier()));
headData.put("DEPARTMENT",
wmsSyncUtils.transferCodeByPk("org_dept", "code", "pk_dept", headVO.getPk_applydept())); // 报检部门必填
headData.put("hedi02", headVO.getPk_applybill() != null ? headVO.getPk_applybill() : ""); // 报检单主键必填
headData.put("hedi03", headVO.getPk_stordoc() != null ? headVO.getPk_stordoc() : ""); // 仓库回传主键
headData.put("hedi05", itemExampleVO.getCsourceid());
headData.put("hedi06", itemExampleVO.getCsourcetypecode());
headData.put("hedi07", wmsSyncUtils.transferFieldByPkAllowNull("sm_user", "user_name", "cuserid", headVO.getBillmaker()));
headData.put("hedi08", wmsSyncUtils.transferCodeByPk(StordocVO.getDefaultTableName(), StordocVO.NAME, StordocVO.PK_STORDOC, headVO.getPk_stordoc()));
//2025年9月7日16点26分--增加检验方案字段--sdlizheng start
// WMS报检单下发WMS新增两个字段pk_defaultstdpk_defaultstd_v WMS回传质检报告时hedi11,hedi12,分别对应pk_chkstdpk_chkstd_v
headData.put("hedi11", wmsSyncUtils.transferCodeByPk("qc_checkstandard", "vchkstandardcode", "pk_checkstandard", headVO.getPk_defaultstd()));
headData.put("hedi12", wmsSyncUtils.transferCodeByPk("qc_checkstandard_v", "vchkstandardcode", "pk_checkstandard", headVO.getPk_defaultstd_v()));
//2025年9月7日16点26分--增加检验方案字段--sdlizheng end
// 构造表体数据遍历itemVOs表体VO数组
// List<Map<String, Object>> bodyDataList = new ArrayList<>();
JSONArray bodyDataList = new JSONArray();
String old_manufacturer = null, old_cprojectid = null, old_productionDept = null, old_vbatchcode = null;
// for (ApplySourceItemVO itemVO : itemVOs) {
// 查询一下上游的到货单明细,然后拿到生产厂商和部门
VOQuery<ArriveItemVO> voQuery = new VOQuery<>(ArriveItemVO.class);
ArriveItemVO[] arriveItemVO = voQuery.query(new String[]{itemVOs[0].getCsourcebid()});
if (arriveItemVO != null && arriveItemVO.length > 0) {
ArriveItemVO arriveItem = arriveItemVO[0];
old_vbatchcode = arriveItem.getVbatchcode();
old_manufacturer = arriveItem.getCproductorid();
old_cprojectid = arriveItem.getCprojectid();
old_productionDept = arriveItem.getVfree1();
}else{
throw new BusinessException("到货单检验推送wms--根据报检单来源子表id【"+itemVOs[0].getCsourcebid()+"】未查询到到货单明细,请检查");
}
// 校验物料属性--2025年9月2日09点50分 变更--如果启用校验报错--不启用则先留存数据清空vo数据后续赋值数据 sdlizheng start
// wmsSyncUtils.checkMaterialBatchCode(itemVOs[0].getPk_material(), itemVOs[0].getVbatchcode(), orgCode);
this.checkMaterialInfo(itemVOs[0], headVO.getPk_stockorg(), arriveItemVO[0]);
// wmsSyncUtils.checkMaterialFreeAssistantProps(itemVOs[0].getPk_material(), orgCode, manufacturer, cprojectid, productionDept);
// 校验物料属性--2025年9月2日09点50分 变更--如果启用校验报错--不启用则先留存数据清空vo数据后续赋值数据 sdlizheng end
// }
// Map<String, Object> bodyData = new HashMap<>();
JSONObject bodyData = new JSONObject();
//2025年10月10日11点29分--增加到货单字段推送wms-start
// 到货单表体自定义项28货位编码发送给WMS的WGKWBH字段传编码
// 到货单表体自定义项29产品编码发送给WMS的CCPBH字段传编码
// 到货单表体自定义项30流程生产订单号发送给WMS的LCSCDDH字段传编码
// 到货单表体生产日期dproducedate字段发送给WMS的JHKGSJ字段传日期
// 到货单表体备注字段vmemob字段发送给WMS的BOMBZ字段传字符串
// 到货单表头的采购部门pk_dept字段发送给WMS的CGBM字段传编码
// 到货单表头的采购员pk_pupsndoc字段发给WMS的CGY字段传编码
VOQuery<ArriveHeaderVO> headQueryVO = new VOQuery<>(ArriveHeaderVO.class);
ArriveHeaderVO[] arriveVOs = headQueryVO.query(new String[]{itemVOs[0].getCsourceid()});
if(arriveVOs==null || arriveVOs.length==0){
throw new BusinessException("到货单检验推送wms--根据报检单来源子表id【"+itemVOs[0].getCsourceid()+"】未查询到到货单明细,请检查");
}
String vbdef28 = arriveItemVO[0].getVbdef28();
bodyData.put("WGKWBH",vbdef28);
String vbdef29 = arriveItemVO[0].getVbdef29();
bodyData.put("CCPBH",vbdef29);
String vbdef30 = arriveItemVO[0].getVbdef30();
bodyData.put("LCSCDDH",vbdef30);
String dproducedate= arriveItemVO[0].getDproducedate() != null ? arriveItemVO[0].getDproducedate().toStdString() : null;
bodyData.put("JHKGSJ", dproducedate);
bodyData.put("BOMBZ", arriveItemVO[0].getVmemob());
String pkDept = arriveVOs[0].getPk_dept();
headData.put("CGBM", wmsSyncUtils.transferCodeByPk("org_dept", "code", "pk_dept", pkDept));
String pkPupsndoc = arriveVOs[0].getPk_pupsndoc();
headData.put("CGY", wmsSyncUtils.transferCodeByPk("bd_psndoc", "code", "pk_psndoc", pkPupsndoc));
//2025年10月10日11点29分--增加到货单字段推送wms-end
//2025年10月17日13点41分--增加数量字段推送wms-start
UFDouble nastnum = arriveItemVO[0].getNastnum()==null?UFDouble.ZERO_DBL:arriveItemVO[0].getNastnum();
bodyData.put("DEDI09", nastnum.toString());
//2025年10月21日10点54分--添加到货字段DEDI10-start
bodyData.put("DEDI10", nastnum.toString());
//2025年10月21日10点54分--添加到货字段DEDI10-end
bodyData.put("DEDI05", wmsSyncUtils.transferCodeByPk("bd_measdoc", "code", "pk_measdoc", arriveItemVO[0].getCastunitid()));
//2025年10月17日13点41分--增加字段推送wms-start
// 检验项目明细表体使用表头物料信息因为itemVO是检验项目明细不是物料明细
bodyData.put("sku", wmsSyncUtils.transferCodeByPk("bd_material", "code", "pk_material",
headVO.getPk_material())); // 产品必填- 使用表头物料
bodyData.put("skuDescr1", wmsSyncUtils.transferFieldByPkAllowNull("bd_material", "materialshortname", "pk_material", headVO.getPk_material())); // 产品描述必填- 使用表头物料
//2025年10月17日13点50分--改取nnum
// bodyData.put("QTY_REJECTED", headVO.getNastnum() != null ? headVO.getNastnum().toString() : ""); // 报检数量必填-
bodyData.put("QTY_REJECTED", headVO.getNnum() != null ? headVO.getNnum().toString() : "");
// 使用表头数量
bodyData.put("qcQty_Completed", headVO.getNnum() != null ? headVO.getNnum().doubleValue() : ""); // 质检数量可选
bodyData.put("LOTATT01",
headVO.getDproducedate() != null ? headVO.getDproducedate().toString() : ""); // 生产日期必填-
bodyData.put("LOTATT04", headVO.getVbatchcode() != null ? headVO.getVbatchcode() : ""); // ERP批次号必填-
// 使用表头批次号
bodyData.put("LOTATT05", wmsSyncUtils.transferCodeByPk("bd_stordoc", "code", "pk_stordoc",
headVO.getPk_stordoc())); // ERP仓库必填- 使用表头仓库
bodyData.put("LOTATT06", wmsSyncUtils.transferCodeByPk("bd_supplier", "code", "pk_supplier",
headVO.getPk_supplier())); // 供应商必填- 使用表头供应商
// 从上游抽出生产厂商字段
bodyData.put("LOTATT07", wmsSyncUtils.transferFieldByPkAllowNull("bd_defdoc", "code", "pk_defdoc", arriveItemVO[0].getCproductorid()));
bodyData.put("LOTATT08", "DJ");
// 项目号必填- 使用表头项目
bodyData.put("LOTATT09", wmsSyncUtils.transferCodeByPk("bd_project", "project_code", "pk_project", arriveItemVO[0].getCprojectid()));
// 检验项目明细相关字段
bodyData.put("DEDI01", itemVOs[0].getCsourcebid());
bodyData.put("DEDI02", headVO.getCtrantypeid()); // 检验项目名称可选
bodyData.put("DEDI03", wmsSyncUtils.transferFieldByPkAllowNull("bd_supplier", "name", "pk_supplier", headVO.getPk_supplier())); // 供应商名称
// bodyData.put("DEDI04", wmsSyncUtils.transferFieldByPkAllowNull("bd_stordoc", "name", "pk_stordoc", headVO.getPk_stordoc())); // ERP仓库名称
//2025年9月28日19点24分--换报检明细主键
bodyData.put("DEDI04", itemVOs[0].getPk_applybill_s());
// 采购部门可选- 使用表头采购部门
bodyData.put("PURCHASE_DEPARMENT", wmsSyncUtils.transferCodeByPk("org_dept", "code", "pk_dept", arriveItemVO[0].getVfree1()));
// 采购员可选- 使用表头采购员
bodyData.put("PURCHASE_CGY", wmsSyncUtils.transferCodeByPk("bd_psndoc", "code", "pk_psndoc", headVO.getPk_pupsndoc()));
// 单位可选- 使用表头单位
bodyData.put("UNIT", wmsSyncUtils.transferCodeByPk("bd_measdoc", "code", "pk_measdoc", headVO.getCastunitid()));
// bodyData.put("addWho", headVO.getCreator() != null ? headVO.getCreator() : ""); // 新增人员可选- 使用表头创建人
String s = wmsSyncUtils.transferCodeByPk("sm_user", "user_code", "cuserid", headVO.getCreator());
//将s转大写
bodyData.put("addWhos",s==null?"" : s.toUpperCase() ); // 新增人员可选- 使用表头创建人
headData.put("addWhos",s==null?"" : s.toUpperCase() ); // 新增人员可选- 使用表头创建人
bodyData.put("addTime", headVO.getCreationtime() != null ? headVO.getCreationtime().toString() : ""); // 新增时间可选- 使用表头创建时间
// bodyData.put("editWho", headVO.getModifier() != null ? headVO.getModifier() : ""); // 编辑人可选- 使用表头修改人
bodyData.put("editWho", wmsSyncUtils.transferCodeByPk("sm_user","user_code","pk_user", headVO.getModifier())); // 新增人员可选- 使用表头创建人
bodyData.put("editTime", headVO.getModifiedtime() != null ? headVO.getModifiedtime().toString() : ""); // 编辑时间可选- 使用表头修改时间
bodyDataList.add(bodyData);
arriveItemVO[0].setVfree1(old_productionDept);
arriveItemVO[0].setVbatchcode(old_vbatchcode);
arriveItemVO[0].setCproductorid(old_manufacturer);
arriveItemVO[0].setCprojectid(old_cprojectid);
// 组装最终数据结构
headData.put("details", bodyDataList);
jsonArray.add(headData);
}
}
private void checkInfo(ApplyVO applyVO) throws BusinessException {
ApplyHeaderVO headVO = applyVO.getHVO();
ApplySourceItemVO[] itemVOs = applyVO.getB2VO();
if (headVO == null) {
throw new BusinessException("报检单表头或明细为空无法构造WMS数据");
}
String vbillcode = headVO.getVbillcode();
if (itemVOs == null || itemVOs.length == 0) {
throw new BusinessException("报检单报检单【" + vbillcode + "】明细为空无法构造WMS数据");
}
String orgCode = null;
try {
orgCode = wmsSyncUtils.transferCodeByPk("org_stockorg", "code", "pk_stockorg", headVO.getPk_stockorg());
} catch (Exception e) {
throw new BusinessException("报检单【" + vbillcode + "】, 查询组织编码失败" + e.getMessage());
}
if (orgCode == null || StringUtils.isEmpty(orgCode)) {
throw new BusinessException("报检单【" + vbillcode + "】, 未获取到组织编码");
}
if (!wmsSyncUtils.checkIfIncludeOrg(orgCode)) {
throw new BusinessException("报检单【" + vbillcode + "】, 不在WMS同步范围内");
}
if ("Y".equalsIgnoreCase(headVO.getVdef3())) {
throw new BusinessException("报检单【" + vbillcode + "】, 已同步成功,无法再次同步");
}
}
/**
* 回写上游到货单明细的自定义项2成功
*/
private void handleUpstreamArriveOrderSuccess(ApplyVO[] applyVOs) throws BusinessException {
//获取所有明细信息
log.error("回写到货单Vbdef22和Vmemob开始--接口失败回滚,接口成功落库");
Set<String> arriveItemIds = new HashSet<>();
for (ApplyVO applyVO : applyVOs) {
String vbillcode = applyVO.getHVO().getVbillcode();
ApplySourceItemVO[] b2VOs = applyVO.getB2VO();
if (b2VOs == null || b2VOs.length < 1) {
throw new BusinessException("发送wms前回写上游到货单失败,明细行为空");
}
for (ApplySourceItemVO itemVO : b2VOs) {
String csourcebid = itemVO.getCsourcebid();
if (StringUtils.isEmpty(csourcebid)) {
throw new BusinessException("发送wms前回写上游到货单失败,明细行[Csourcebid]字段为空");
}
arriveItemIds.add(csourcebid);
}
}
VOQuery<ArriveItemVO> voQuery = new VOQuery<>(ArriveItemVO.class);
ArriveItemVO[] arriveItems = voQuery.query(arriveItemIds.toArray(new String[0]));
if (arriveItems == null || arriveItems.length < 1) {
throw new BusinessException("发送wms前回写上游到货单失败,未查询到上游到货单明细信息");
}
//检查回写的到货单是否为质检的
for (ArriveItemVO arriveItem : arriveItems) {
String vbdef50 = arriveItem.getVbdef50();
String pkOrderB = arriveItem.getPk_order_b();
if(!"Y".equals(vbdef50)){
throw new BusinessException("请检查,存在到货单明细为免检,生成报检单,到货单明细【"+pkOrderB+"");
}
arriveItem.setVbdef22("Y"); // 标记同步成功
arriveItem.setVmemob("发送WMS成功"); // 记录失败原因
arriveItem.setStatus(1);
}
new VOUpdate<ArriveItemVO>().update(arriveItems, new String[]{"vbdef22", "vmemob"});
log.error("回写到货单Vbdef22和Vmemob结束--接口失败回滚,接口成功落库");
}
private void checkMaterialInfo(ApplySourceItemVO itemVO, String orgCode, ArriveItemVO arriveItemVO) throws BusinessException {
String materialPk = itemVO.getPk_material();
String vbatchcode = arriveItemVO.getVbatchcode();
String manufacturer = arriveItemVO.getCproductorid();
String projectNo = arriveItemVO.getCprojectid();
String productionDept = arriveItemVO.getVfree1();
if (materialPk == null || materialPk.trim().isEmpty()) {
log.error("物料主键为空,无法检查自由辅助属性");
throw new BusinessException("物料主键为空");
}
if (orgCode == null || orgCode.trim().isEmpty()) {
log.error("组织主键为空,无法检查自由辅助属性");
throw new BusinessException("组织主键为空");
}
try {
// 查询物料库存信息中的自由辅助属性
String sql = "SELECT fixasst2, fixasst4, freeasst1,wholemanaflag " +
"FROM bd_materialstock " +
"WHERE pk_material = ? AND pk_org = ?";
SQLParameter sqlParameter = new SQLParameter();
sqlParameter.addParam(materialPk);
sqlParameter.addParam(orgCode);
Object result = dao.executeQuery(sql, sqlParameter, (ResultSetProcessor) rs -> {
if (rs.next()) {
Map<String, String> row = new HashMap<>();
row.put("fixasst2", rs.getString("fixasst2")); // 对应项目号
row.put("fixasst4", rs.getString("fixasst4")); // 对应生产厂商
row.put("freeasst1", rs.getString("freeasst1")); // 对应生产部门
row.put("wholemanaflag", rs.getString("wholemanaflag")); // 批次管理标识
return row;
}
return null;
});
if (result == null) {
log.error("未查询到物料库存信息,物料主键:" + materialPk + ",组织主键:" + orgCode);
throw new BusinessException("未查询到物料库存信息,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
@SuppressWarnings("unchecked")
Map<String, String> materialStockInfo = (Map<String, String>) result;
log.debug("查询到物料库存信息,物料主键:" + materialPk + ",组织主键:" + orgCode +
",自由辅助属性配置:" + materialStockInfo);
// 如果物料启用了批次管理
String batchManageFlag = materialStockInfo.get("wholemanaflag");
if ("Y".equals(batchManageFlag)) {
if (vbatchcode == null || vbatchcode.trim().isEmpty()) {
log.error("物料启用了批次管理,但批次号为空,物料主键:" + materialPk);
throw new BusinessException("物料启用了批次管理,但批次号为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("物料启用了批次管理且批次号不为空,检查通过,物料主键:" + materialPk + ",批次号:" + vbatchcode);
} else {
if (vbatchcode != null && !vbatchcode.trim().isEmpty()) {
log.error("物料没有启用批次管理,但批次号不为空,物料主键:" + materialPk);
arriveItemVO.setVbatchcode(null);
// throw new BusinessException("物料没有启用批次管理,但批次号不为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
// 不需要批次管理的物料直接返回true
log.debug("物料未启用批次管理,检查通过,物料主键:" + materialPk);
}
// 检查项目号对应fixasst2
String projectFlag = materialStockInfo.get("fixasst2");
if ("Y".equals(projectFlag)) {
if (projectNo == null || projectNo.trim().isEmpty()) {
log.error("物料启用了项目号属性,但项目号为空,物料主键:" + materialPk);
throw new BusinessException("物料启用了项目号属性,但项目号为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("项目号属性校验通过,物料主键:" + materialPk + ",项目号:" + projectNo);
} else {
if (projectNo != null && !projectNo.trim().isEmpty()) {
log.error("物料未启用项目号属性,但项目号不为空,物料主键:" + materialPk);
arriveItemVO.setCprojectid(null);
// throw new BusinessException("物料未启用项目号属性,但项目号不为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("物料未启用项目号属性,跳过校验,物料主键:" + materialPk);
}
// 检查生产厂商对应fixasst4
String manufacturerFlag = materialStockInfo.get("fixasst4");
if ("Y".equals(manufacturerFlag)) {
if (manufacturer == null || manufacturer.trim().isEmpty()) {
log.error("物料启用了生产厂商属性,生产厂商不能为空,物料主键:" + materialPk);
throw new BusinessException("物料启用了生产厂商属性,生产厂商不能为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("生产厂商属性校验通过,物料主键:" + materialPk + ",生产厂商:" + manufacturer);
} else {
if (manufacturer != null && !manufacturer.trim().isEmpty()) {
log.error("物料未启用生产厂商属性,生产厂商应为空,物料主键:" + materialPk);
arriveItemVO.setCproductorid(null);
// throw new BusinessException("物料未启用生产厂商属性,生产厂商应为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("物料未启用生产厂商属性,跳过校验,物料主键:" + materialPk);
}
//2025年8月28日15点32分--生产部门按照物料基本信息页签控制 --start
IMaterialPubService_C marService = NCLocator.getInstance().lookup(IMaterialPubService_C.class);
Map<String, MaterialVO> materialMap = marService.queryMaterialBaseInfoByPks(new String[]{materialPk},
new String[]{MaterialVO.PK_MARASSTFRAME, MaterialVO.NAME, MaterialVO.NAME2, MaterialVO.NAME3,
MaterialVO.NAME4, MaterialVO.NAME5, MaterialVO.NAME6});
Set<String> marFramePkSet = new HashSet<String>();
for (Map.Entry<String, MaterialVO> entry : materialMap.entrySet()) {
String pk_marasstframe = entry.getValue().getPk_marasstframe();
if (pk_marasstframe != null) {
marFramePkSet.add(pk_marasstframe);
}
}
Map<String, List<Integer>> marFrameMap = MarAssistantCheckUtils
.queryMarAsstFrameIncludeDefPropIndex(marFramePkSet.toArray(new String[0]));
if (marFrameMap == null || marFrameMap.size() < 1) {
if (productionDept != null && !productionDept.trim().isEmpty()) {
log.error("物料基础信息页签未启用生产部门属性,但生产部门不为空,物料主键:" + materialPk);
arriveItemVO.setVfree1(null);
// throw new BusinessException("物料基础信息页签未启用生产部门属性,但生产部门不为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("物料基础信息页签未启用生产部门属性,跳过校验,物料主键:" + materialPk);
} else {
String pkMarasstframe = materialMap.get(materialPk).getPk_marasstframe();
List<Integer> integers = marFrameMap.get(pkMarasstframe);
if (integers.contains(6)) {
//启用生产部门
if (productionDept == null || productionDept.trim().isEmpty()) {
log.error("物料基础信息页签启用了生产部门属性,但生产部门为空,物料主键:" + materialPk);
throw new BusinessException("物料基础信息页签启用了生产部门属性,但生产部门为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
log.debug("生产部门属性校验通过,物料主键:" + materialPk + ",生产部门:" + productionDept);
} else {
if (productionDept != null && !productionDept.trim().isEmpty()) {
log.error("物料基础信息页签未启用生产部门属性,但生产部门不为空,物料主键:" + materialPk);
arriveItemVO.setVfree1(null);
// throw new BusinessException("物料基础信息页签未启用生产部门属性,但生产部门不为空,物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
}
}
//2025年8月28日15点32分--生产部门按照物料基本信息页签控制 --end
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("检查物料自由辅助属性失败:" + e.getMessage() + ",物料主键:" + materialPk + ",组织主键:" + orgCode, e);
throw new BusinessException("检查物料自由辅助属性失败:" + e.getMessage() + ",物料编码:" + this.transferCodeByPk(MaterialVO.getDefaultTableName(), MaterialVO.CODE, MaterialVO.PK_MATERIAL, materialPk));
}
}
public String transferCodeByPk(String tableName, String selectField, String pkField, String pk) throws BusinessException {
if (pk == null || pk.trim().isEmpty()) {
log.error("未传入主键信息,无法查询编码:" + pkField + ":" + tableName + ":" + selectField);
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();
}
/**
* 根据表体源头单据类型编码确定WMS订单类型
*
* @param itemVOs 报检点明细数组
* @return WMS订单类型
*/
private String getAsnTypeByFirstTypeCode(ApplySourceItemVO[] itemVOs) throws BusinessException {
if (itemVOs == null || itemVOs.length == 0) {
log.error("ArriveForQCImpl - 报检点明细为空使用默认类型CGRK");
throw new BusinessException("报检点明细为空无法确定WMS订单类型");
}
// 取第一个表体行的源头单据类型编码
String firstTypeCode = itemVOs[0].getCfirsttypecode();
if (StringUtils.isEmpty(firstTypeCode)) {
log.error("ArriveForQCImpl - 源头单据类型编码为空使用默认类型CGRK");
throw new BusinessException("源头单据类型编码为空无法确定WMS订单类型");
}
return switch (firstTypeCode) {
case "21" -> // 采购订单
"CGRK";
case "61" -> // 委外订单
"WWRK";
default -> {
log.error("ArriveForQCImpl - 未知的源头单据类型编码: " + firstTypeCode + ",不同步此报检单");
yield null;
}
};
}
}

View File

@ -0,0 +1,57 @@
package nc.itf.pu.m23.qc;
import nc.vo.pu.m23.entity.ArriveItemVO;
import nc.vo.pu.m23.entity.ArriveVO;
import nc.vo.pub.BusinessException;
import nc.vo.qc.c001.entity.ApplyVO;
/**
* <p>
* <b>到货单的针对质量管理的接口定义,本类主要完成以下功能</b>
* <ul>
* <li>到货单的质检
* <li>到货单的反检
* </ul>
* <p>
* <p>
*
* @version 6.0
* @since 6.0
* @author hanbin
* @time 2010-1-11 下午01:40:39
*/
public interface IArriveForQC {
/**
* 方法功能描述>到货单的反检
* <p>
* <b>参数说明</b>
*
* @param aggVO
* @throws BusinessException
* <p>
* @since 6.0
* @author hanbin
* @time 2010-1-13 上午09:43:38
*/
public ArriveItemVO[] antiQualityCheck(ArriveItemVO[] bills) throws BusinessException;
/**
* 方法功能描述到货单的质检
* <p>
* <b>参数说明</b>
*
* @param aggVO
* @param isCheck 免检存货是否报检
* @throws BusinessException
* <p>
* @since 6.0
* @author hanbin
* @time 2010-1-13 上午09:43:38
*/
public Object[] qualityCheck(ArriveVO[] bills, boolean isCheck)
throws BusinessException;
public ApplyVO[] pushWmsByArriveVOs(ArriveVO[] bills)
throws Exception;
}