diff --git a/ic/src/private/nc/bs/ic/m4c/sign/SignBP.java b/ic/src/private/nc/bs/ic/m4c/sign/SignBP.java new file mode 100644 index 0000000..96970de --- /dev/null +++ b/ic/src/private/nc/bs/ic/m4c/sign/SignBP.java @@ -0,0 +1,61 @@ +package nc.bs.ic.m4c.sign; + +import com.yonyou.cloud.ncc.plugin.entity.OperationInfo; +import nc.bs.ic.general.sign.ISignBP; +import nc.bs.ic.general.sign.ISignRuleProvider; +import nc.bs.ic.general.sign.SignBPTemplate; +import nc.bs.ic.m4c.base.BPPlugInPoint; +import nc.bs.ic.m4c.base.rule.SaleOutFillInvoiceNumRule; +import nc.bs.ic.m4c.sign.rule.*; +import nc.bs.ic.pub.util.SagasUtils; +import nc.bs.scmpub.rule.VOSagaFrozenValidateRule; +import nc.impl.pubapp.pattern.rule.processer.AroundProcesser; +import nc.itf.ic.m4c.compensate.ISaleOutSagasCompensate; +import nc.vo.ic.m4c.entity.SaleOutVO; +import nc.vo.ic.pub.util.VOEntityUtil; +import nc.vo.scmpub.res.billtype.ICBillType; +import nccloud.bs.ic.mobile.component.operation.rule.MobAfterSignMessageRule; +import nccloud.bs.ic.tms.kj.KJTMSConfirmAction; +import nccloud.vo.scmpub.tms.enumeration.BusiScene; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class SignBP implements ISignBP, ISignRuleProvider { + public SignBP() { + } + + public SaleOutVO[] sign(SaleOutVO[] bills) { + SignBPTemplate signBP = new SignBPTemplate(BPPlugInPoint.SignBP, this); + SagasUtils.frozenAndAddSaga(bills, ICBillType.SaleOut.getCode(), "1", (OperationInfo) null); + Map paramMap = new HashMap(); + paramMap.put("actionname", "sign_4C"); + paramMap.put("hid", VOEntityUtil.getPksFromAggVO(bills)); + SagasUtils.compensate(paramMap, ISaleOutSagasCompensate.class); + SaleOutVO[] resultVOs = (SaleOutVO[]) signBP.sign(bills); + KJTMSConfirmAction action = new KJTMSConfirmAction(BusiScene.SODelivery); + action.confirm(resultVOs); + return resultVOs; + } + + public void addAfterRule(SaleOutVO[] vos, AroundProcesser processor) { + processor.addAfterRule(new PushSquareSignRule()); + processor.addAfterRule(new AfterSignRuleForSquareiaProcess()); + processor.addAfterRule(new AfterSignRuleForFinanceProcess()); + processor.addAfterRule(new SaleOutFillInvoiceNumRule()); + processor.addAfterRule(new AfterSignRuleForLiabilityProcess()); + processor.addAfterRule(new SaleOutProceedsRule()); + processor.addAfterRule(new AfterRedSignRuleTOArsubProcess()); + processor.addAfterRule(new ArsubToVoucherRule()); + processor.addAfterRule(new SaleOutProceedsRuleCG()); + processor.addAfterRule(new MobAfterSignMessageRule()); + // 销售出库 签字后 同步到MES金思维系统 + processor.addAfterRule(new AfterSigningSynchronizeRule()); + // 盘点(审批后传MES) + } + + public void addBeforeRule(SaleOutVO[] vos, AroundProcesser processor) { + processor.addBeforeRule(new VOSagaFrozenValidateRule(true)); + } +} \ No newline at end of file diff --git a/ic/src/private/nc/bs/ic/m4c/sign/rule/AfterSigningSynchronizeRule.java b/ic/src/private/nc/bs/ic/m4c/sign/rule/AfterSigningSynchronizeRule.java new file mode 100644 index 0000000..1ecd1f0 --- /dev/null +++ b/ic/src/private/nc/bs/ic/m4c/sign/rule/AfterSigningSynchronizeRule.java @@ -0,0 +1,190 @@ +package nc.bs.ic.m4c.sign.rule; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yonyou.cloud.utils.StringUtils; +import nc.IHttpPostOtherSys; +import nc.bs.framework.common.NCLocator; +import nc.bs.logging.Log; +import nc.impl.pubapp.pattern.rule.IRule; +import nc.vo.ic.m4c.entity.SaleOutBodyVO; +import nc.vo.ic.m4c.entity.SaleOutHeadVO; +import nc.vo.ic.m4c.entity.SaleOutVO; +import nc.vo.pub.BusinessException; +import nc.vo.pub.lang.UFDate; + +import java.text.SimpleDateFormat; + + +//销售出库(签字后传MES金思维系统) +public class AfterSigningSynchronizeRule implements IRule { + private static final String SALE_OUT_URL = "/GTHINKING/AjaxService/N_MISPRO/SaleOrderOutbound.ashx/SaveData"; // 销售出库登记接口 + private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final String logginfo = "OALOG"; + private static final Log obmlog = Log.getInstance(logginfo); + + public AfterSigningSynchronizeRule() { + } + + @Override + public void process(SaleOutVO[] saleOutVOS) { + try { + if (saleOutVOS == null || saleOutVOS.length == 0) { + return; + } + // 初始化HTTP请求工具类 + IHttpPostOtherSys httpPostOtherSys = NCLocator.getInstance().lookup(IHttpPostOtherSys.class); + // 处理每个销售出库单 + for (SaleOutVO saleOutVO : saleOutVOS) { + SaleOutHeadVO hvo = (SaleOutHeadVO) saleOutVO.getParentVO(); + SaleOutBodyVO[] bvos = (SaleOutBodyVO[]) saleOutVO.getChildrenVO(); + // 构建要发送的数据 + JSONObject syncData = buildSyncData(hvo, bvos); + // 发送数据到金思维系统(使用HttpPostOtherSysImpl处理网络请求) + String mesResponse = httpPostOtherSys.callLE(SALE_OUT_URL, syncData); + obmlog.debug("AfterSigningSynchronizeRule-金思维系统响应: " + mesResponse); + // 解析响应,处理结果 + processResponse(hvo.getVbillcode(), mesResponse); + } + } catch (Exception e) { + obmlog.error("AfterSigningSynchronizeRule-处理异常:" + e.getMessage(), e); + } + } + + /** + * 构建符合金思维系统接口规范的请求数据 + * 按照NCC/YonBIP字段映射到金思维系统字段 + */ + private JSONObject buildSyncData(SaleOutHeadVO hvo, SaleOutBodyVO[] bvos) { + JSONObject requestData = new JSONObject(); + requestData.put("operation_type", "I"); + + JSONObject info = new JSONObject(); + // 主表数据 - 根据字典字段映射 + info.put("orderNo", hvo.getVbillcode()); // 提货单ID - 单据号(vbillcode) + // 日期格式转换 + UFDate dbilldate = hvo.getDbilldate(); + String billDateStr = dateTimeFormat.format(dbilldate.toDate()); + info.put("orderDate", billDateStr); // 提单日期 - 单据日期(dbilldate) + info.put("planDate", billDateStr); // 计划日期 - 使用同样的单据日期 + info.put("actureDate", billDateStr); + // 生成方式可能存储在自定义字段中 + String genType = getStringValue(hvo.getVdef1()); + info.put("genType", null); // 生成方式 - 默认N + info.put("type", "XSCK"); // 默认事务类型XSCK + info.put("departmentId", hvo.getCdptvid()); // 部门ID - 部门(cdptvid) + info.put("storeId", hvo.getCwarehouseid()); // 仓库ID - 仓库(cwarehouseid) + // 汇率默认为1 + info.put("exRate", null); + info.put("sType", "N"); // 发出默认值 + info.put("billing", "Y"); // 出具发票默认值 + info.put("billingBasis", "S"); // 开票依据默认值 + + // 有效日期可能为空,可能存储在其他字段或自定义字段中 + String effDateStr = getStringValue(hvo.getVdef2()); + if (StringUtils.isNotEmpty(effDateStr)) { + try { + UFDate effDate = new UFDate(effDateStr); + info.put("effDate", dateTimeFormat.format(effDate.toDate())); + } catch (Exception e) { + obmlog.error("解析有效日期出错: " + e.getMessage()); + } + } + + info.put("consignStoreId", null); // 寄售仓库ID + info.put("consignType", null); // 寄售事务类型 + info.put("operatorNo", null); // 经办人工号 - 制单人(billmaker) + info.put("operatorName", null); // 经办人 - 可能是自定义字段 + info.put("storeKeeper", hvo.getCwhsmanagerid()); // 保管员 - 库管员(cwhsmanagerid) + info.put("cwhsmanagerid", hvo.getCwhsmanagerid()); // 保管员ID - 库管员(cwhsmanagerid) + info.put("customId", hvo.getCcustomerid()); // 客户ID - 订单客户(ccustomerid) + info.put("mark", "Y"); // 生成标志默认值 + info.put("remark", hvo.getVnote()); // 备注 - 备注(vnote) + + // 构建details明细数组 + JSONArray details = new JSONArray(); + if (bvos != null) { + for (SaleOutBodyVO bvo : bvos) { + JSONObject detail = new JSONObject(); + detail.put("orderNo", hvo.getVbillcode()); // 提货单ID - 单据号(vbillcode) + detail.put("sequenceNum", bvo.getCrowno()); + + // 来源单据信息 - 根据字典正确映射 + detail.put("saleOrderNo", null); // SOID - 来源单据号(vsourcebillcode) + detail.put("saleSequenceNum", null); // SO序号 - 来源单据行号(vsourcerowno) + detail.put("allocationNum", null); // 分配号 + + // 物料相关 - 使用正确的字段名 + detail.put("materialId", bvo.getCmaterialoid()); // 物料ID - 物料(cmaterialoid) + detail.put("unit", bvo.getCunitid()); // 计量单位 - 主单位(cunitid) + detail.put("productNum", null); // 制令号 - 可能是自定义字段 + + detail.put("storageId", bvo.getClocationid()); // 库位 - 货位(clocationid) + detail.put("batchNum", bvo.getVbatchcode()); // 物料批号 - 批次号(vbatchcode) + detail.put("scaleFactor", bvo.getVchangerate()); + + // 应发数量和实发数量 + detail.put("issuedQty", bvo.getNshouldassistnum()); // 应发数量(nshouldassistnum) + detail.put("mIssuedQty", bvo.getNshouldnum()); // 主应发数量(nshouldnum) + detail.put("actQry", bvo.getNassistnum()); // 实发数量(nassistnum) + detail.put("mActQry", bvo.getNnum()); // 主实发数量(nnum) + detail.put("assistActQry", null); // 辅助实发数量(nassistnum) + + // 客户信息 + detail.put("customId", getStringValue(bvo.getCasscustid())); // 客户ID - 客户(casscustid) + // 供应商信息 + detail.put("supplierId", getStringValue(bvo.getCvendorid())); // 供应商ID - 供应商(cvendorid) + detail.put("color", null); + // 生产日期 + detail.put("manufactureDate", null); // 生产日期(dproducedate) + detail.put("properties", null); + detail.put("remark", bvo.getVnotebody()); // 备注 - 行备注(vnotebody) + + details.add(detail); + } + } + info.put("details", details); + + // 将info对象添加到请求数据中 + requestData.put("info", info); + + return requestData; + } + + /** + * 安全获取字符串值,防止空指针异常 + */ + private String getStringValue(Object value) { + return value == null ? "" : value.toString(); + } + + /** + * 处理金思维系统响应 + */ + private void processResponse(String vbillcode, String response) { + if (StringUtils.isEmpty(response)) { + obmlog.error("AfterSigningSynchronizeRule-响应为空,单据号: " + vbillcode); + return; + } + + try { + JSONObject respObj = JSONObject.parseObject(response); + JSONObject result = respObj.getJSONObject("result"); + if (result != null) { + boolean success = result.getBooleanValue("success"); + String message = result.getString("message"); + String errorMessage = result.getString("errorMessage"); + String orderNo = result.getString("orderNo"); + + if (success) { + obmlog.info("AfterSigningSynchronizeRule-同步成功,单据号: " + vbillcode + ", 返回单号: " + orderNo + ", 消息: " + message); + } else { + obmlog.error("AfterSigningSynchronizeRule-同步失败,单据号: " + vbillcode + ", 错误: " + errorMessage); + throw new BusinessException("同步到金思维系统失败: " + errorMessage); + } + } + } catch (Exception e) { + obmlog.error("AfterSigningSynchronizeRule-处理响应异常: " + e.getMessage(), e); + } + } +} diff --git a/ic/src/private/nc/bs/ic/m4r/approve/ApproveBP.java b/ic/src/private/nc/bs/ic/m4r/approve/ApproveBP.java new file mode 100644 index 0000000..edd4eda --- /dev/null +++ b/ic/src/private/nc/bs/ic/m4r/approve/ApproveBP.java @@ -0,0 +1,32 @@ +package nc.bs.ic.m4r.approve; + +import nc.bs.ic.m4r.approve.rule.AfterApprovingSynchronizeRule; +import nc.bs.ic.m4r.approve.rule.PushInOutBills; +import nc.bs.ic.m4r.base.BPPluginPoint; +import nc.bs.ic.m4r.insert.rule.InvcountDataCheck; +import nc.bs.ic.pub.base.ICAroundProcesser; +import nc.bs.ic.special.approve.ApproveBPTemplate; +import nc.bs.ic.special.approve.IApproveBP; +import nc.bs.ic.special.approve.rule.SpecialAuditDataCheck; +import nc.bs.ic.special.base.IApproveRuleProvider; +import nc.bs.pub.compiler.AbstractCompiler2; +import nc.vo.ic.m4r.entity.InvCountBillVO; + +public class ApproveBP implements IApproveBP, IApproveRuleProvider { + public ApproveBP() { + } + + public InvCountBillVO[] approve(InvCountBillVO[] bills, AbstractCompiler2 script) { + return (InvCountBillVO[]) (new ApproveBPTemplate(BPPluginPoint.ApproveBP, this)).approve(bills, script); + } + + public void addApproveAfterRule(ICAroundProcesser processor) { + processor.addAfterRule(new PushInOutBills()); + // 盘点(审批后传MES) + processor.addAfterRule(new AfterApprovingSynchronizeRule()); + } + + public void addApproveBeforeRule(ICAroundProcesser processor) { + processor.replaceBeforeRuleAt(new InvcountDataCheck(), SpecialAuditDataCheck.class); + } +} \ No newline at end of file diff --git a/ic/src/private/nc/bs/ic/m4r/approve/rule/AfterApprovingSynchronizeRule.java b/ic/src/private/nc/bs/ic/m4r/approve/rule/AfterApprovingSynchronizeRule.java new file mode 100644 index 0000000..40cf1d2 --- /dev/null +++ b/ic/src/private/nc/bs/ic/m4r/approve/rule/AfterApprovingSynchronizeRule.java @@ -0,0 +1,176 @@ +package nc.bs.ic.m4r.approve.rule; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yonyou.cloud.utils.StringUtils; +import nc.IHttpPostOtherSys; +import nc.bs.framework.common.NCLocator; +import nc.bs.logging.Log; +import nc.impl.pubapp.pattern.rule.IRule; +import nc.vo.ic.m4r.entity.InvCountBillVO; +import nc.vo.ic.m4r.entity.InvCountHeaderVO; +import nc.vo.ic.m4r.entity.InvCountBodyVO; +import nc.vo.pub.BusinessException; +import nc.vo.pub.lang.UFDate; +import nc.vo.pub.lang.UFDouble; + +import java.text.SimpleDateFormat; + + +// 盘点(审批后传MES) +public class AfterApprovingSynchronizeRule implements IRule { + private static final String INV_COUNT_URL = "/GTHINKING/AjaxService/N_MISPRO/InvCount.ashx/SaveData"; // 盘点单同步接口 + private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final String logginfo = "OALOG"; + private static final Log obmlog = Log.getInstance(logginfo); + + public AfterApprovingSynchronizeRule() { + } + + @Override + public void process(InvCountBillVO[] invCountBillVOs) { + try { + if (invCountBillVOs == null || invCountBillVOs.length == 0) { + return; + } + + // 初始化HTTP请求工具类 + IHttpPostOtherSys httpPostOtherSys = NCLocator.getInstance().lookup(IHttpPostOtherSys.class); + + // 处理每个盘点单 + for (InvCountBillVO invCountBillVO : invCountBillVOs) { + InvCountHeaderVO hvo = invCountBillVO.getParentVO(); + InvCountBodyVO[] bvos = invCountBillVO.getChildrenVO(); + + // 构建要发送的数据 + JSONObject syncData = buildSyncData(hvo, bvos); + + // 发送数据到金思维系统(使用HttpPostOtherSysImpl处理网络请求) + String mesResponse = httpPostOtherSys.callLE(INV_COUNT_URL, syncData); + obmlog.debug("AfterApprovingSynchronizeRule-金思维系统响应: " + mesResponse); + + // 解析响应,处理结果 + processResponse(hvo.getVbillcode(), mesResponse); + } + } catch (Exception e) { + obmlog.error("AfterApprovingSynchronizeRule-处理异常:" + e.getMessage(), e); + } + } + + /** + * 构建符合金思维系统接口规范的请求数据 + * 按照接口文档要求构建JSON结构 + */ + private JSONObject buildSyncData(InvCountHeaderVO hvo, InvCountBodyVO[] bvos) throws BusinessException { + JSONObject requestData = new JSONObject(); + // 操作类型为新增 + requestData.put("operation_type", "I"); + + // 构建info对象 - 按照接口要求设置必填字段 + JSONObject info = new JSONObject(); + + // 必填字段 + info.put("storeId", hvo.getCwarehouseid()); // 仓库ID(cwarehouseid) - 必填 + info.put("departmentId", hvo.getCdptvid()); // 部门ID(cdptvid) - 必填 + + // 日期处理 - 盘点日期 + UFDate dcountdate = hvo.getDcountdate(); + if (dcountdate != null) { + info.put("date", dateTimeFormat.format(dcountdate.toDate())); // 盘点日期(dcountdate) - 必填 + } else { + // 如果盘点日期为空,使用单据日期 + UFDate dbilldate = hvo.getDbilldate(); + if (dbilldate != null) { + info.put("date", dateTimeFormat.format(dbilldate.toDate())); + } else { + // 接口要求此字段必填,如果没有日期则使用当前日期 + info.put("date", dateTimeFormat.format(new java.util.Date())); + } + } + + // 其他主表字段 + info.put("worker", getStringValue(hvo.getCountoperator())); // 盘点人(countoperator) + info.put("mark", "N"); // 生成标志,默认为N + info.put("remark", getStringValue(hvo.getVnote())); // 备注(vnote) + + // 构建details明细数组 + JSONArray details = new JSONArray(); + if (bvos != null) { + for (InvCountBodyVO bvo : bvos) { + JSONObject detail = new JSONObject(); + + // 必填字段 + // 序号 - 转换为浮点数 + detail.put("sequenceNum", bvo.getCrowno()); // 序号(crowno) - 必填 + detail.put("materialId", getStringValue(bvo.getCmaterialvid())); // 物料ID(cmaterialvid) - 必填 + detail.put("storageId", getStringValue(bvo.getClocationid())); // 库位(clocationid) - 必填 + detail.put("batchNum", getStringValue(bvo.getVbatchcode())); // 物料批号(vbatchcode) - 必填 + + // 盘存数量 - 使用实盘主数量 + UFDouble countNum = bvo.getNcountnum(); + if (countNum != null) { + detail.put("panQty", countNum.doubleValue()); // 盘存数量(ncountnum) - 必填 + } else { + throw new BusinessException("盘存数量不能为空"); + } + + detail.put("customId", getStringValue(bvo.getCasscustid())); // 客户ID + detail.put("supplierId", getStringValue(bvo.getCvendorid())); // 供应商ID + + // 生产日期处理 + detail.put("manufactureDate", null); // 如果没有,传入null + detail.put("color", null); + + // 包装信息(可能来自自定义属性) + detail.put("packLen", null); + detail.put("packSize", null); + // 备注 + detail.put("remark", getStringValue(bvo.getVnotebody())); // 备注(vnotebody) + details.add(detail); + } + } + info.put("details", details); + + // 将info对象添加到请求数据中 + requestData.put("info", info); + + return requestData; + } + + /** + * 安全获取字符串值,防止空指针异常 + */ + private String getStringValue(Object value) { + return value == null ? "" : value.toString(); + } + + /** + * 处理金思维系统响应 + */ + private void processResponse(String vbillcode, String response) { + if (StringUtils.isEmpty(response)) { + obmlog.error("AfterApprovingSynchronizeRule-响应为空,单据号: " + vbillcode); + return; + } + + try { + JSONObject respObj = JSONObject.parseObject(response); + JSONObject result = respObj.getJSONObject("result"); + if (result != null) { + boolean success = result.getBooleanValue("success"); + String message = result.getString("message"); + String errorMessage = result.getString("errorMessage"); + String orderNo = result.getString("orderNo"); + + if (success) { + obmlog.info("AfterApprovingSynchronizeRule-同步成功,单据号: " + vbillcode + ", 返回单号: " + orderNo + ", 消息: " + message); + } else { + obmlog.error("AfterApprovingSynchronizeRule-同步失败,单据号: " + vbillcode + ", 错误: " + errorMessage); + throw new BusinessException("同步到金思维系统失败: " + errorMessage); + } + } + } catch (Exception e) { + obmlog.error("AfterApprovingSynchronizeRule-处理响应异常: " + e.getMessage(), e); + } + } +}