From 6e7f80cab56bda9e19ceddfc5c145384615775b0 Mon Sep 17 00:00:00 2001 From: mzr Date: Thu, 17 Apr 2025 15:41:26 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=80=E5=94=AE=E5=8F=91=E7=A5=A8=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BB=A3=E7=A0=81=E5=90=88=E5=B9=B6=EF=BC=8C=E7=94=A8?= =?UTF-8?q?2=E4=B8=AAResource=E4=BC=9A=E6=8F=90=E7=A4=BA:resource=20notfou?= =?UTF-8?q?nd,please=20check=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- so/META-INF/{saveCommit.rest => SaleInv.rest} | 2 +- so/META-INF/SaleRedInv.rest | 6 - .../saleinvoice/operator/BillSaveAction.java | 397 ----------- .../operator/IAPISaleInvMaitainImpl.java | 645 ++++++++++++++++++ .../saleinvoice/operator/SaleInvResource.java | 76 +++ .../operator/saveCommitAction.java | 431 ------------ 6 files changed, 722 insertions(+), 835 deletions(-) rename so/META-INF/{saveCommit.rest => SaleInv.rest} (64%) delete mode 100644 so/META-INF/SaleRedInv.rest delete mode 100644 so/src/public/nccloud/api/so/saleinvoice/operator/BillSaveAction.java create mode 100644 so/src/public/nccloud/api/so/saleinvoice/operator/IAPISaleInvMaitainImpl.java create mode 100644 so/src/public/nccloud/api/so/saleinvoice/operator/SaleInvResource.java delete mode 100644 so/src/public/nccloud/api/so/saleinvoice/operator/saveCommitAction.java diff --git a/so/META-INF/saveCommit.rest b/so/META-INF/SaleInv.rest similarity index 64% rename from so/META-INF/saveCommit.rest rename to so/META-INF/SaleInv.rest index 52fd99a9..2376205a 100644 --- a/so/META-INF/saveCommit.rest +++ b/so/META-INF/SaleInv.rest @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/so/META-INF/SaleRedInv.rest b/so/META-INF/SaleRedInv.rest deleted file mode 100644 index 8e9487b8..00000000 --- a/so/META-INF/SaleRedInv.rest +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/so/src/public/nccloud/api/so/saleinvoice/operator/BillSaveAction.java b/so/src/public/nccloud/api/so/saleinvoice/operator/BillSaveAction.java deleted file mode 100644 index 2d10b235..00000000 --- a/so/src/public/nccloud/api/so/saleinvoice/operator/BillSaveAction.java +++ /dev/null @@ -1,397 +0,0 @@ -package nccloud.api.so.saleinvoice.operator; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import nc.bs.framework.common.NCLocator; -import nc.bs.framework.core.util.ObjectCreator; -import nc.bs.logging.Logger; -import nc.bs.trade.business.HYSuperDMO; -import nc.itf.uap.IUAPQueryBS; -import nc.jdbc.framework.processor.MapProcessor; -import nc.pubitf.so.m32.api.ISaleinvoiceQueryAPI; -import nc.vo.pub.BusinessException; -import nc.vo.pub.lang.UFBoolean; -import nc.vo.pub.lang.UFDate; -import nc.vo.pub.lang.UFDouble; -import nc.vo.pubapp.calculator.HslParseUtil; -import nc.vo.pubapp.pattern.tool.performance.DeepCloneTool; -import nc.vo.scmpub.res.billtype.SOBillType; -import nc.vo.so.m32.entity.SaleInvoiceBVO; -import nc.vo.so.m32.entity.SaleInvoiceHVO; -import nc.vo.so.m32.entity.SaleInvoiceVO; -import nc.vo.sscivm.ivsale.IVApplicationAggVO; -import nc.vo.sscivm.ivsale.IVApplicationBodyVO; -import nc.vo.sscivm.ivsale.IVApplicationHeadVO; -import nccloud.api.baseapp.exchange.convert.IExchangeForService; -import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataObject; -import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataResult; -import nccloud.api.rest.utils.ResultMessageUtil; -import nccloud.commons.lang.StringUtils; -import nccloud.itf.sscivm.ivsale.impl.IVApplicationServiceImpl; -import nccloud.pubitf.riart.pflow.CloudPFlowContext; -import nccloud.pubitf.riart.pflow.ICloudScriptPFlowService; -import nccloud.ws.rest.resource.AbstractNCCRestResource; -import org.json.JSONString; - -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import java.util.List; -import java.util.Map; - -/** - * 销售发票红冲接口 - * - * @author lj - * @date 2025/03/14 - * @update 20250415 mzr修改 - */ -@Path("so/saleinvoice/operator") -public class BillSaveAction extends AbstractNCCRestResource { - - public static String fplxStr = "";// 开票申请发票类型 - - public static DeepCloneTool deepCloneTool; - - public static DeepCloneTool getCloneTool() { - if (deepCloneTool == null) { - deepCloneTool = new DeepCloneTool(); - } - return deepCloneTool; - } - - public BillSaveAction() { - - } - - public OpenApiConvertDataResult changeToExchangeData(OpenApiConvertDataObject openApiConvertDataObject) - throws Exception { - return getPFxxEJBService().changeToExchangeData(openApiConvertDataObject); - } - - public static IExchangeForService getPFxxEJBService() { - IExchangeForService exchangeForService = (IExchangeForService) ObjectCreator.newInstance("ufesbexpress", - "nccloud.pubimpl.pfxx.convert.ExchangeForServiceImpl"); - return exchangeForService; - } - - @Override - public String getModule() { - return "so"; - } - - @POST - @Path("/billSaveRp") - @Consumes({"application/json"}) - @Produces({"application/json"}) - public JSONString billSaveRp(JSONString json) throws Exception { - /** - * 销售发票红冲: - * 1.根据bip传参中的销售发票主表id查询erp的销售发票VO - * 2.根据查询的销售发票VO生成红冲的销售发票 - */ - JSONObject jobject = JSONObject.parseObject(json.toJSONString()); - if (jobject == null) { - return ResultMessageUtil.exceptionToJSON(new NullPointerException("JSONString:null")); - } - JSONObject bject = jobject.getJSONObject("billhead"); - if (bject == null) { - return ResultMessageUtil.exceptionToJSON(new NullPointerException("billhead:null")); - } - // 销售发票id - String csaleinvoiceid = bject.getString("vdef40"); - // 根据销售发票主实体id查询销售发票 - String[] ids = {csaleinvoiceid}; - SaleInvoiceVO[] saleInvoiceVOs = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) - .queryVOByIDs(ids); - if (saleInvoiceVOs == null || saleInvoiceVOs.length <= 0) { - return ResultMessageUtil.exceptionToJSON(new NullPointerException("未在系统中查询到对应的销售发票")); - } - try { - // 调用函数根据原销售发票组装新红冲发票 - SaleInvoiceVO saleInvoiceRedRushVO = makeNewRedRushSaleInvoice(saleInvoiceVOs[0], bject); - // 生成红冲发票 - ICloudScriptPFlowService flowService = NCLocator.getInstance().lookup(ICloudScriptPFlowService.class); - CloudPFlowContext context = new CloudPFlowContext(); - context.setBillType("32"); - context.setBillVos(new SaleInvoiceVO[]{saleInvoiceRedRushVO}); - context.setActionName("WRITE"); - SaleInvoiceVO[] returnSaveSaleInvoiceVOs = (SaleInvoiceVO[]) flowService.exeScriptPFlow(context); - Logger.error("=========================inv-save============== "); - if (returnSaveSaleInvoiceVOs != null && returnSaveSaleInvoiceVOs.length > 0) { - Logger.error("inv-save = " + JSONArray.toJSONString(returnSaveSaleInvoiceVOs)); - // 生成红冲发票成功后,执行销售发票审批动作 - context.setBillType("32"); - context.setBillVos(returnSaveSaleInvoiceVOs); - context.setActionName("APPROVE"); - SaleInvoiceVO[] returnApproveSaleInvoiceVOs = (SaleInvoiceVO[]) flowService.exeScriptPFlow(context); - if (returnApproveSaleInvoiceVOs == null || returnApproveSaleInvoiceVOs.length <= 0) { - throw new BusinessException("生成销售发票审核失败"); - } - Logger.error("=========================inv-audit============== "); - Logger.error("inv-audit = " + JSONArray.toJSONString(returnApproveSaleInvoiceVOs)); - /** - * 开票申请红冲逻辑: - * 1.根据销售发票号查询下游开票申请 - * 2.根据原开票申请生成新红冲 - */ - String vBillcode = saleInvoiceVOs[0].getParentVO().getVbillcode(); - HYSuperDMO dmo = new HYSuperDMO(); - // 开票申请单主表 - IVApplicationHeadVO[] iVApplicationHeadVO = (IVApplicationHeadVO[]) dmo.queryByWhereClause(IVApplicationHeadVO.class, "src_billno='" + vBillcode + "' and dr=0 "); - String pk_ivapplication = iVApplicationHeadVO[0].getPk_ivapplication(); // 开票申请id - // 开票申请单子表 - IVApplicationBodyVO[] iVApplicationBodyVOs = (IVApplicationBodyVO[]) dmo.queryByWhereClause(IVApplicationBodyVO.class, "pk_ivapplication='" + pk_ivapplication + "' and dr=0 "); - // 调用函数封装开票申请红冲VO - IVApplicationAggVO iVApplicationAggVO = makeNewRedRushIVApplicationAggVO(iVApplicationHeadVO[0], iVApplicationBodyVOs, bject, returnApproveSaleInvoiceVOs); - // 生成红冲的开票申请 - IVApplicationServiceImpl serviceImpl = new IVApplicationServiceImpl(); - IVApplicationAggVO returnSaveIVApplicationAggVO = serviceImpl.save(iVApplicationAggVO); - if (returnSaveIVApplicationAggVO != null) { - return ResultMessageUtil.toJSON(returnApproveSaleInvoiceVOs, "接口调用成功"); - } else { - Exception e = new Exception("接口调用失败"); - return ResultMessageUtil.exceptionToJSON(e); - } - } else { - Exception e = new Exception("接口调用失败"); - return ResultMessageUtil.exceptionToJSON(e); - } - } catch (Exception e) { - Logger.error("billSaveRp-exp: ", e); - return ResultMessageUtil.exceptionToJSON(e); - } - } - - /** - * 构造红冲发票VO - * - * @param originalVO - * @param bject - * @return - * @throws Exception - */ - public static SaleInvoiceVO makeNewRedRushSaleInvoice(SaleInvoiceVO originalVO, JSONObject bject) throws Exception { - try { - SaleInvoiceVO saleInvoiceVO = new SaleInvoiceVO(); - // 发票主实体 - SaleInvoiceHVO saleInvoiceHVO = originalVO.getParentVO(); - // 发票子实体数组 - SaleInvoiceBVO[] saleInvoiceBVOs = originalVO.getChildrenVO(); - // 发票新主实体 - SaleInvoiceHVO newSaleInvoiceHVO = new SaleInvoiceHVO(); - - // 单据日期 - UFDate dbilldate = new UFDate(bject.getString("dbilldate")); - // 制单日期 - UFDate dmakedate = new UFDate(bject.getString("creationtime")); - - // 子实体属性赋值 - UFDouble sumNum = new UFDouble(); // 合计数量 - UFDouble sumNtax = new UFDouble(); // 合计税额 - UFDouble sumNcaltaxmny = new UFDouble(); // 合计计税金额 - UFDouble sumNorigmny = new UFDouble(); // 合计无税金额 - UFDouble sumNorigtaxmny = new UFDouble(); // 合计价税合计 - int i = 0; - // 参数子实体数组 - com.alibaba.fastjson.JSONArray bvoJsonArr = (com.alibaba.fastjson.JSONArray) bject.get("csaleinvoicebid"); - List bvoList = bvoJsonArr.toJavaList(JSONObject.class); - SaleInvoiceBVO[] newSaleInvoiceBVOs = new SaleInvoiceBVO[bvoList.size()]; // 新子实体 - for (SaleInvoiceBVO saleInvoiceBVO : saleInvoiceBVOs) { - String csaleinvoicebid = saleInvoiceBVO.getCsaleinvoicebid(); // 子表id - // 筛选参数红冲的子表集合 - List newBvoArr = bvoList.stream().filter(item -> { - String parCsaleinvoicebid = item.getString("vbdef15") + ""; // 子表id - return csaleinvoicebid.equals(parCsaleinvoicebid); - }).toList(); - if (newBvoArr.size() <= 0) { - continue; - } - JSONObject bipBvoJson = newBvoArr.get(0); // 参数子表 - SaleInvoiceBVO newInvBVO = new SaleInvoiceBVO(); - // 克隆取值原子表销售发票 - newInvBVO = (SaleInvoiceBVO) getCloneTool().deepClone(saleInvoiceBVO); - // 赋值之后修改子实体红冲时字段 - newInvBVO.setCsaleinvoicebid(null); // 发票子实体id - newInvBVO.setDbilldate(dbilldate); // 开票日期 - String vchangerate = "1/1"; // 换算率 - Map soMap = getSaleOrderInfo(bipBvoJson.getString("csrcbid")); - if (soMap != null && StringUtils.isNotEmpty(soMap.getOrDefault("vchangerate", "") + "")) { - vchangerate = soMap.get("vchangerate") + ""; // 销售订单的换算率 - } - newInvBVO.setVchangerate(vchangerate); // 换算率 - UFDouble[] vchangerateNums = HslParseUtil.parseHsl(vchangerate); - UFDouble vchangerateNum = UFDouble.ONE_DBL; - if (null != vchangerateNums && vchangerateNums.length != 0) { - vchangerateNum = vchangerateNums[0].div(vchangerateNums[1]).setScale(2, 4); - } - // BIP合同平台的数量对应BIP2312的主数量,BIP2312的 数量=主数量*换算关系 - UFDouble nastnum = new UFDouble(bipBvoJson.getString("nastnum")); - newInvBVO.setNastnum(nastnum.multiply(vchangerateNum).setScale(2, 4)); // 数量 - newInvBVO.setNnum(nastnum); // 主数量 - newInvBVO.setNtax(new UFDouble(bipBvoJson.getString("ntax"))); // 税额 - newInvBVO.setNmny(new UFDouble(bipBvoJson.getString("nmny"))); // 本币无税金额 - newInvBVO.setNtaxmny(new UFDouble(bipBvoJson.getString("ntaxmny"))); // 本币价税合计 - newInvBVO.setNcaltaxmny(new UFDouble(bipBvoJson.getString("ncaltaxmny"))); // 计税金额 - newInvBVO.setNorigmny(new UFDouble(bipBvoJson.getString("norigmny"))); // 无税金额 - newInvBVO.setNorigtaxmny(new UFDouble(bipBvoJson.getString("norigtaxmny"))); // 价税合计 - newInvBVO.setCopposesrcbid(bipBvoJson.getString("vbdef15")); // 对冲来源子表id - newInvBVO.setNqtunitnum(null); // 报价数量 - newInvBVO.setCsaleinvoiceid(null); // 发票关联主表id - newInvBVO.setNtotalcostnum(null); // 累计成本结算数量 - newInvBVO.setNtotalincomemny(null); // 累计确认应收金额 - newInvBVO.setNtotalincomenum(null); // 累计确认应收数量 - newSaleInvoiceBVOs[i++] = newInvBVO; - sumNum = sumNum.add(new UFDouble(bipBvoJson.getString("nnum"))); - sumNtax = sumNtax.add(new UFDouble(bipBvoJson.getString("ntax"))); - sumNcaltaxmny = sumNcaltaxmny.add(new UFDouble(bipBvoJson.getString("ncaltaxmny"))); - sumNorigmny = sumNorigmny.add(new UFDouble(bipBvoJson.getString("norigmny"))); - sumNorigtaxmny = sumNorigtaxmny.add(new UFDouble(bipBvoJson.getString("norigtaxmny"))); - } - - // 克隆取值原子表销售发票 - newSaleInvoiceHVO = (SaleInvoiceHVO) getCloneTool().deepClone(saleInvoiceHVO); - // 赋值之后修改主实体红冲时字段 - newSaleInvoiceHVO.setCsaleinvoiceid(null); // 发票主实体id - newSaleInvoiceHVO.setVbillcode(null); // 发票号 - newSaleInvoiceHVO.setDbilldate(dbilldate); // 开票日期 - newSaleInvoiceHVO.setDmakedate(dmakedate); // 制单日期 - newSaleInvoiceHVO.setBsubunitflag(UFBoolean.TRUE); // 冲抵标记 - newSaleInvoiceHVO.setFopposeflag(2); // 对冲标记 (2:对冲生成) - newSaleInvoiceHVO.setFstatusflag(1); // 单据状态 (1:自由态) - newSaleInvoiceHVO.setNtotalastnum(null); // 总数量 - newSaleInvoiceHVO.setNtotalorigsubmny(null); // 冲抵金额 - newSaleInvoiceHVO.setNtotalorigmny(null); // 价税合计 - newSaleInvoiceHVO.setVopposesrccode(saleInvoiceHVO.getVbillcode()); // 对冲来源发票号 - newSaleInvoiceHVO.setCopposesrcid(saleInvoiceHVO.getCsaleinvoiceid()); // 对冲来源发票id - newSaleInvoiceHVO.setApprover(null); // 审批人 - newSaleInvoiceHVO.setTaudittime(null); // 审批日期 - - // 组装VO - saleInvoiceVO.setParentVO(newSaleInvoiceHVO); - saleInvoiceVO.setChildrenVO(newSaleInvoiceBVOs); - return saleInvoiceVO; - } catch (Exception e) { - throw new BusinessException(e.getMessage()); - } - } - - /** - * 构造红冲开票申请VO - * - * @param applyHeadVO 原开票申请主实体 - * @param ivApplicationBodyVOS 原开票申请子实体 - * @param bject bip参数 - * @param returnApproveSaleInvoiceVOs 新生成的红冲销售发票实体 - * @return - * @throws Exception - */ - public static IVApplicationAggVO makeNewRedRushIVApplicationAggVO(IVApplicationHeadVO applyHeadVO, IVApplicationBodyVO[] ivApplicationBodyVOS, JSONObject bject, SaleInvoiceVO[] returnApproveSaleInvoiceVOs) throws Exception { - try { - IVApplicationAggVO applicationAggVO = new IVApplicationAggVO(); - IVApplicationHeadVO newivApplicationHeadVO = new IVApplicationHeadVO(); // 新主实体 - - // 取新生成红冲发票的主实体数据 - String csaleinvoiceid = returnApproveSaleInvoiceVOs[0].getParentVO().getCsaleinvoiceid(); - String[] ids = {csaleinvoiceid}; - SaleInvoiceVO[] rpSaleInvoiceVOs = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) - .queryVOByIDs(ids); - SaleInvoiceHVO rpSaleInvoiceHVO = rpSaleInvoiceVOs[0].getParentVO(); - - // 主实体属性赋值 - // 克隆取值原子表开票申请 - newivApplicationHeadVO = (IVApplicationHeadVO) getCloneTool().deepClone(applyHeadVO); - // 根据参数判断是否为部分红冲 - boolean isPartHCFlag = false; - UFDouble paramNtotalorigmny = new UFDouble(bject.getString("ntotalorigmny")); // 参数价税合计(主表红冲金额) - UFDouble ntotalorigmny = applyHeadVO.getJshj(); // 原开票申请主表价税合计 - // 红冲金额与开票申请源价税合计比较如果和值大于零,则为部分红冲 - if (ntotalorigmny.add(paramNtotalorigmny).compareTo(UFDouble.ZERO_DBL) > 0) { - isPartHCFlag = true; - } - UFDouble sumXmsl = new UFDouble(); // 合计数量 - UFDouble sumXmje = new UFDouble(); // 合计金额 - UFDouble sumXmjshj = new UFDouble(); // 合计价税合计 - UFDouble sumBchcje = new UFDouble(); // 合计本次红冲金额 - UFDouble sumSe = new UFDouble(); // 合计税额 - // 子实体属性赋值 - int i = 0; - // 参数子实体数组 - com.alibaba.fastjson.JSONArray bvoJsonArr = (com.alibaba.fastjson.JSONArray) bject.get("csaleinvoicebid"); - List bvoList = bvoJsonArr.toJavaList(JSONObject.class); - IVApplicationBodyVO[] newivApplicationBodyVOS = new IVApplicationBodyVO[bvoList.size()]; // 新子实体 - for (IVApplicationBodyVO ivApplicationBodyVO : ivApplicationBodyVOS) { - String src_pkdetail = ivApplicationBodyVO.getSrc_pkdetail(); // 来源单据行id - // 筛选参数红冲的子表集合 - List newBvoArr = bvoList.stream().filter(item -> { - String parCsaleinvoicebid = item.getString("vbdef15") + ""; // 子表id - return src_pkdetail.equals(parCsaleinvoicebid); - }).toList(); - if (newBvoArr.size() <= 0) { - continue; - } - JSONObject bipBvoJson = newBvoArr.get(0); // 参数子表 - IVApplicationBodyVO newivApplicationBodyVO = new IVApplicationBodyVO(); -// BeanUtil.copyProperties(ivApplicationBodyVO,newivApplicationBodyVO, CopyOptions.create().setIgnoreNullValue(true)); - // 克隆取值原子表开票申请 - newivApplicationBodyVO = (IVApplicationBodyVO) getCloneTool().deepClone(ivApplicationBodyVO); - // 赋值之后修改子实体红冲时字段 - newivApplicationBodyVO.setPk_ivappdetail(null); // 开票申请子实体id - newivApplicationBodyVO.setBillno(null); // 开票申请子实体单据号 - newivApplicationBodyVO.setSe(new UFDouble(bipBvoJson.getString("ntax"))); // 税额 - newivApplicationBodyVO.setXmsl(new UFDouble(bipBvoJson.getString("nnum"))); // 数量 - newivApplicationBodyVO.setXmje(new UFDouble(bipBvoJson.getString("norigmny"))); // 金额 - newivApplicationBodyVO.setXmjshj(new UFDouble(bipBvoJson.getString("norigtaxmny"))); // 价税合计 - // 本次红冲金额 = 本次参数红冲金额 - newivApplicationBodyVO.setBchcje(new UFDouble(bipBvoJson.getString("norigtaxmny")).multiply(new UFDouble(-1))); - newivApplicationBodyVOS[i++] = newivApplicationBodyVO; - sumSe = sumSe.add(new UFDouble(bipBvoJson.getString("ntax"))); - sumXmsl = sumXmsl.add(new UFDouble(bipBvoJson.getString("nnum"))); - sumXmje = sumXmje.add(new UFDouble(bipBvoJson.getString("norigmny"))); - sumXmjshj = sumXmjshj.add(new UFDouble(bipBvoJson.getString("norigtaxmny"))); - sumBchcje = sumBchcje.add(new UFDouble(bipBvoJson.getString("norigtaxmny")).multiply(new UFDouble(-1))); - } - // 赋值之后修改主实体红冲时字段 - newivApplicationHeadVO.setPk_ivapplication(null); // 开票申请单主实体id - newivApplicationHeadVO.setBillno(null); // 单据号 - newivApplicationHeadVO.setPreparedate(new UFDate(bject.getString("dbilldate"))); // 单据日期 - newivApplicationHeadVO.setJshj(sumXmjshj); // 价税合计 - newivApplicationHeadVO.setHjje(sumXmje); // 合计金额 - newivApplicationHeadVO.setHjse(sumSe); // 合计税额 - newivApplicationHeadVO.setBchcje(sumBchcje); // 本次红冲金额 - newivApplicationHeadVO.setHzfp(UFBoolean.TRUE); // 红字发票 - newivApplicationHeadVO.setSrc_billtype(SOBillType.Invoice.getCode()); // 来源单据类型 - newivApplicationHeadVO.setSrc_tradetype(rpSaleInvoiceHVO.getCtrantypeid()); // 来源交易类型 - newivApplicationHeadVO.setTranstypecode(rpSaleInvoiceHVO.getVtrantypecode()); // 来源交易类型编码 - newivApplicationHeadVO.setSrc_pkbusibill(rpSaleInvoiceHVO.getCsaleinvoiceid()); // 来源单据id - newivApplicationHeadVO.setSrc_billno(rpSaleInvoiceHVO.getVbillcode()); // 来源单据编号 - newivApplicationHeadVO.setHcyy("2"); // 红冲原因:2(开票有误) - - // 组装VO - applicationAggVO.setParentVO(newivApplicationHeadVO); - applicationAggVO.setChildrenVO(newivApplicationBodyVOS); - return applicationAggVO; - } catch (Exception e) { - throw new BusinessException(e.getMessage()); - } - } - - public IUAPQueryBS getQueryService() { - return NCLocator.getInstance().lookup(IUAPQueryBS.class); - } - - - private static Map getSaleOrderInfo(String csaleorderbid) throws BusinessException { - IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); - String sql = " select s.vbillcode,s.csaleorderid, s.corigcurrencyid," + - " sb.csaleorderbid,sb.crowno,sb.blargessflag,sb.nexchangerate," + - " nvl(sb.vchangerate, '1/1') vchangerate, bdc.code currencycode" + - " from so_saleorder_b sb" + - " inner join so_saleorder s on sb.csaleorderid=s.csaleorderid" + - " left join bd_currtype bdc on s.corigcurrencyid=bdc.pk_currtype" + - " where sb.csaleorderbid='" + csaleorderbid + "' "; - return (Map) queryBS.executeQuery(sql, new MapProcessor()); - } - -} \ No newline at end of file diff --git a/so/src/public/nccloud/api/so/saleinvoice/operator/IAPISaleInvMaitainImpl.java b/so/src/public/nccloud/api/so/saleinvoice/operator/IAPISaleInvMaitainImpl.java new file mode 100644 index 00000000..9844d78f --- /dev/null +++ b/so/src/public/nccloud/api/so/saleinvoice/operator/IAPISaleInvMaitainImpl.java @@ -0,0 +1,645 @@ +package nccloud.api.so.saleinvoice.operator; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import nc.bs.framework.common.InvocationInfoProxy; +import nc.bs.framework.common.NCLocator; +import nc.bs.logging.Logger; +import nc.bs.trade.business.HYSuperDMO; +import nc.itf.uap.IUAPQueryBS; +import nc.jdbc.framework.processor.ColumnProcessor; +import nc.jdbc.framework.processor.MapProcessor; +import nc.pubitf.so.m32.api.ISaleinvoiceQueryAPI; +import nc.vo.pub.BusinessException; +import nc.vo.pub.lang.UFBoolean; +import nc.vo.pub.lang.UFDate; +import nc.vo.pub.lang.UFDouble; +import nc.vo.pubapp.calculator.HslParseUtil; +import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill; +import nc.vo.pubapp.pattern.tool.performance.DeepCloneTool; +import nc.vo.pubapp.pflow.PfUserObject; +import nc.vo.scmpub.res.billtype.SOBillType; +import nc.vo.so.m32.entity.SaleInvoiceBVO; +import nc.vo.so.m32.entity.SaleInvoiceHVO; +import nc.vo.so.m32.entity.SaleInvoiceVO; +import nc.vo.sscivm.ivsale.IVApplicationAggVO; +import nc.vo.sscivm.ivsale.IVApplicationBodyVO; +import nc.vo.sscivm.ivsale.IVApplicationHeadVO; +import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataObject; +import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataResult; +import nccloud.api.rest.utils.ResultMessageUtil; +import nccloud.commons.lang.StringUtils; +import nccloud.dto.scmpub.script.entity.SCMScriptResultDTO; +import nccloud.itf.sscivm.ivsale.impl.IVApplicationServiceImpl; +import nccloud.pubitf.riart.pflow.CloudPFlowContext; +import nccloud.pubitf.riart.pflow.ICloudScriptPFlowService; +import nccloud.pubitf.scmpub.commit.service.IBatchRunScriptService; +import nccloud.pubitf.scmpub.ssc.service.ISSCService; +import nccloud.pubitf.so.saleinvoice.service.ISaleInvoiceToTaxInvService; +import nccloud.pubitf.ssctp.sscbd.lientage.ISSClientageMatchService; +import org.json.JSONString; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Map; + +public class IAPISaleInvMaitainImpl { + + public static String fplxStr = "";// 开票申请发票类型 + + public static DeepCloneTool deepCloneTool; + + public static DeepCloneTool getCloneTool() { + if (deepCloneTool == null) { + deepCloneTool = new DeepCloneTool(); + } + return deepCloneTool; + } + + public JSONString saveBlue(JSONObject jobject) throws Exception { + JSONObject ufinterfaceObj = jsonObjectAss(jobject); + String tsType = ufinterfaceObj.getString("tsType"); + if (tsType != null && tsType.equals("1")) { + Exception e = new NullPointerException("销售订单查询关联失败!"); + return ResultMessageUtil.exceptionToJSON(e); + } + JSONObject bjects = ufinterfaceObj.getJSONObject("ufinterface"); + String billtype = bjects.getString("billtype"); + String account = bjects.getString("account"); + String omscode = bjects.getString("orgcode"); + String groupcode = bjects.getString("groupcode"); + + if (billtype != null && account != null && groupcode != null && "32".equals(billtype)) { + OpenApiConvertDataObject openApiconvertData0bject = new OpenApiConvertDataObject(); + openApiconvertData0bject.setAccount(account); + openApiconvertData0bject.setBilltype(billtype); + openApiconvertData0bject.setGroupcode(groupcode); + openApiconvertData0bject.setOpenApiJsonData(ufinterfaceObj); + + OpenApiJsonConvertToExChangeXmlService oService = new OpenApiJsonConvertToExChangeXmlService(); + OpenApiConvertDataResult r = oService.changeToExchangeData(openApiconvertData0bject); + JSONObject returnJson = r.getDesc(); + String content = ""; + // 逐层解析 JSON 数据 + JSONObject ufinterface = returnJson.getJSONObject("ufinterface"); + if (ufinterface != null) { + JSONArray sendResultArray = ufinterface.getJSONArray("sendresult"); + if (sendResultArray != null && !sendResultArray.isEmpty()) { + // 提取 content 字段 + content = sendResultArray.getJSONObject(0).getString("content"); + } + } + if (content == null || content.equals("")) { + return r != null + ? ResultMessageUtil.toJSON(r.getDesc(), "0") + : ResultMessageUtil.exceptionToJSON(new NullPointerException("未知异常")); + } + String[] ids = {content}; + SaleInvoiceVO[] saleInvoiceVO = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) + .queryVOByIDs(ids); + SaleInvoiceVO saleInvoiceVO22 = saleInvoiceVO[0]; + SaleInvoiceHVO saleInvoiceHVO = saleInvoiceVO22.getParentVO(); + // 销售发票审核开始 + InvocationInfoProxy.getInstance().setUserId(saleInvoiceHVO.getApprover()); + CloudPFlowContext context = new CloudPFlowContext(); + context.setBillType("32"); + context.setBillVos(new SaleInvoiceVO[]{saleInvoiceVO[0]}); + ISSCService sscService = (ISSCService) NCLocator.getInstance().lookup(ISSCService.class); + String[] actionNames = sscService.isStartSSCWorkFlow( + (AbstractBill[]) ((AbstractBill[]) context.getBillVos()), ISSClientageMatchService.BusiUnitTypeEnum.SO); + context.setActionName("APPROVE"); + context.setTrantype("32-02"); + context.setBatch(false); + context.setBatchUserObj(new PfUserObject[]{new PfUserObject()}); + IBatchRunScriptService service = (IBatchRunScriptService) NCLocator.getInstance() + .lookup(IBatchRunScriptService.class); + SCMScriptResultDTO result = service.runBacth(context, SaleInvoiceVO.class); + // 销售发票审核结束 + ISaleInvoiceToTaxInvService invoiceService = NCLocator.getInstance() + .lookup(ISaleInvoiceToTaxInvService.class); + // 数电票(增值税专用发票)=31,数电票(普通发票)=32,数电纸质发票(机动车销售统一发票)=36,数电纸质发票(增值税专用发票)=33,数电纸质发票(普通发票)=34, + // 增值税电子普通发票=1,增值税电子专用发票=2,增值税普通发票=3,增值税专用发票=4,增值税电子普通发票(成品油)=8,成品油普通发票(卷式)=9, + // 成品油普通发票=10,成品油专用发票=11,增值税普通发票(卷式)=12,增值税专用发票(机动车)=99 + invoiceService.issueTaxInvoice(saleInvoiceVO, fplxStr); + + JSONObject desc = r.getDesc(); + if (desc != null) { + // 发票的全部信息都返回给合同平台 + desc.put("vos", saleInvoiceVO); + } + return ResultMessageUtil.toJSON(desc, "0"); + } else { + Exception e = new NullPointerException( + "billtype:" + billtype + ",account:" + account + ",groupcode:" + groupcode); + return ResultMessageUtil.exceptionToJSON(e); + } + } + + public JSONString saveRed(JSONObject jobject) throws Exception { + /** + * 销售发票红冲: + * 1.根据bip传参中的销售发票主表id查询erp的销售发票VO + * 2.根据查询的销售发票VO生成红冲的销售发票 + */ + JSONObject bject = jobject.getJSONObject("billhead"); + if (bject == null) { + return ResultMessageUtil.exceptionToJSON(new NullPointerException("billhead:null")); + } + // 销售发票id + String csaleinvoiceid = bject.getString("vdef40"); + // 根据销售发票主实体id查询销售发票 + String[] ids = {csaleinvoiceid}; + SaleInvoiceVO[] saleInvoiceVOs = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) + .queryVOByIDs(ids); + if (saleInvoiceVOs == null || saleInvoiceVOs.length <= 0) { + return ResultMessageUtil.exceptionToJSON(new NullPointerException("未在系统中查询到对应的销售发票")); + } + // 调用函数根据原销售发票组装新红冲发票 + SaleInvoiceVO saleInvoiceRedRushVO = makeNewRedRushSaleInvoice(saleInvoiceVOs[0], bject); + // 生成红冲发票 + ICloudScriptPFlowService flowService = NCLocator.getInstance().lookup(ICloudScriptPFlowService.class); + CloudPFlowContext context = new CloudPFlowContext(); + context.setBillType("32"); + context.setBillVos(new SaleInvoiceVO[]{saleInvoiceRedRushVO}); + context.setActionName("WRITE"); + SaleInvoiceVO[] returnSaveSaleInvoiceVOs = (SaleInvoiceVO[]) flowService.exeScriptPFlow(context); + Logger.error("=========================inv-save============== "); + if (returnSaveSaleInvoiceVOs != null && returnSaveSaleInvoiceVOs.length > 0) { + Logger.error("inv-save = " + JSONArray.toJSONString(returnSaveSaleInvoiceVOs)); + // 生成红冲发票成功后,执行销售发票审批动作 + context.setBillType("32"); + context.setBillVos(returnSaveSaleInvoiceVOs); + context.setActionName("APPROVE"); + SaleInvoiceVO[] returnApproveSaleInvoiceVOs = (SaleInvoiceVO[]) flowService.exeScriptPFlow(context); + if (returnApproveSaleInvoiceVOs == null || returnApproveSaleInvoiceVOs.length <= 0) { + throw new BusinessException("生成销售发票审核失败"); + } + Logger.error("=========================inv-audit============== "); + Logger.error("inv-audit = " + JSONArray.toJSONString(returnApproveSaleInvoiceVOs)); + /** + * 开票申请红冲逻辑: + * 1.根据销售发票号查询下游开票申请 + * 2.根据原开票申请生成新红冲 + */ + String vBillcode = saleInvoiceVOs[0].getParentVO().getVbillcode(); + HYSuperDMO dmo = new HYSuperDMO(); + // 开票申请单主表 + IVApplicationHeadVO[] iVApplicationHeadVO = (IVApplicationHeadVO[]) dmo.queryByWhereClause(IVApplicationHeadVO.class, "src_billno='" + vBillcode + "' and dr=0 "); + String pk_ivapplication = iVApplicationHeadVO[0].getPk_ivapplication(); // 开票申请id + // 开票申请单子表 + IVApplicationBodyVO[] iVApplicationBodyVOs = (IVApplicationBodyVO[]) dmo.queryByWhereClause(IVApplicationBodyVO.class, "pk_ivapplication='" + pk_ivapplication + "' and dr=0 "); + // 调用函数封装开票申请红冲VO + IVApplicationAggVO iVApplicationAggVO = makeNewRedRushIVApplicationAggVO(iVApplicationHeadVO[0], iVApplicationBodyVOs, bject, returnApproveSaleInvoiceVOs); + // 生成红冲的开票申请 + IVApplicationServiceImpl serviceImpl = new IVApplicationServiceImpl(); + IVApplicationAggVO returnSaveIVApplicationAggVO = serviceImpl.save(iVApplicationAggVO); + if (returnSaveIVApplicationAggVO != null) { + return ResultMessageUtil.toJSON(returnApproveSaleInvoiceVOs, "接口调用成功"); + } else { + Exception e = new Exception("接口调用失败"); + return ResultMessageUtil.exceptionToJSON(e); + } + } else { + Exception e = new Exception("接口调用失败"); + return ResultMessageUtil.exceptionToJSON(e); + } + } + + public static JSONObject jsonObjectAss(JSONObject originalJson) throws Exception { + try { + // 构建目标 JSON 格式 + JSONObject resultJson = new JSONObject(); + // 添加 ufinterface 字段 + JSONObject ufinterface = new JSONObject(); + ufinterface.put("billtype", "32"); + ufinterface.put("sender", "BIP_NC"); + ufinterface.put("level", "0"); + ufinterface.put("replace", "Y"); + ufinterface.put("roottag", "bill"); + ufinterface.put("isexchange", "Y"); + ufinterface.put("account", "01"); + ufinterface.put("groupcode", "00"); + // 处理 bill 数组 + JSONArray billArray = new JSONArray(); + JSONObject bill = new JSONObject(); + // billhead 结构 + JSONObject billhead = new JSONObject(); + billhead = originalJson.getJSONObject("billhead");// 传入JSON对象 + billhead.put("pk_org_v", originalJson.getJSONObject("billhead").getString("pk_org"));// 开票组织版本=开票组织 + billhead.put("pk_group", "00");// 集团 + fplxStr = originalJson.getJSONObject("billhead").getString("vdef22"); + billhead.put("vtrantypecode", "32-02");// 发票类型编码 + billhead.put("cbiztypeid", "SO01");// 业务流程 + billhead.put("approver", "BIP");// 审批人 + billhead.put("fstatusflag", 1);// 单据状态 + billhead.put("billmaker", "BIP");// 制单人 + billhead.put("csendcountryid", "CN");// 发货国家 + billhead.put("crececountryid", "CN");// 收货国家 + billhead.put("ctaxcountryid", "CN");// 报税国家 + // 2025-2-8付业要求修改,根据发票类型Q(自定义档案)对照发票类型 + String ctrantypeidStr = "32-02";// 默认普通发票 + if (fplxStr != null && fplxStr.equals("31")) { + ctrantypeidStr = "32-01";// 数电票(增值税专用发票) + } else if (fplxStr != null && fplxStr.equals("32")) { + ctrantypeidStr = "32-02";// 数电票(普通发票) + } else if (fplxStr != null && fplxStr.equals("36")) { + ctrantypeidStr = "32-Cxx-03";// 机动车销售发票 + } + billhead.put("ctrantypeid", ctrantypeidStr);// 发票类型 + // billhead.put("ctrantypeid", "32-02");//发票类型 + billhead.put("fbuysellflag", "1");// 购销类型 + billhead.put("creator", "BIP");// 创建人 + billhead.put("ccurrencyid", "CNY");// 本位币 + billhead.put("corigcurrencyid", "CNY");// 币种 + billhead.put("nexchangerate", 1);// 折本汇率 + billhead.put("btriatradeflag", 0);// 三角贸易 + JSONObject newItem = new JSONObject(); + JSONObject otherJson = new JSONObject(); + JSONArray csaleinvoicebid = new JSONArray(); + // 遍历原始数据中的 csaleinvoicebid 数组 + for (int i = 0; i < originalJson.getJSONObject("billhead").getJSONArray("csaleinvoicebid").size(); i++) { + JSONObject item = originalJson.getJSONObject("billhead").getJSONArray("csaleinvoicebid") + .getJSONObject(i); + + JSONObject itemDetails = new JSONObject(); + itemDetails = item; + itemDetails.put("carorgid", originalJson.getJSONObject("billhead").getString("pk_org"));// 应收组织 + itemDetails.put("csendstockorgid", originalJson.getJSONObject("billhead").getString("pk_org"));// 库存组织原始版本 + itemDetails.put("cmaterialid", item.getString("cmaterialvid"));// 物料编码 + Map value2 = getSaleorderVo(item.getString("csrcbid")); + if (value2 == null) { + resultJson = new JSONObject(); + resultJson.put("tsType", "1"); + return resultJson; + } + itemDetails.put("vfirsttype", "30");// 源头单据类型 + itemDetails.put("vfirstcode", value2.get("vbillcode"));// 源头单据号 + itemDetails.put("blargessflag", value2.get("blargessflag"));// 赠品 + itemDetails.put("vfirsttrantype", "30-01");// 源头交易类型 + itemDetails.put("vfirstrowno", value2.get("crowno"));// 源头单据行号 + itemDetails.put("cfirstid", item.getString("csrcid"));// 源头单据主表 + itemDetails.put("cfirstbid", item.getString("csrcbid"));// 源头单据子表 + itemDetails.put("vsrctype", "30");// 来源单据类型 + itemDetails.put("vsrccode", value2.get("vbillcode"));// 来源单据号 + itemDetails.put("vsrctrantype", "30-01");// 来源交易类型 + itemDetails.put("vsrcrowno", value2.get("crowno"));// 来源单据行号 + // 通过 ntaxrate 获取 taxcode + String taxcodeStr = getTaxcode(item.getString("ntaxrate")); + // 将 taxcodeStr 放入 bodyMap + itemDetails.put("ctaxcodeid", taxcodeStr);// 税码 + itemDetails.put("nnum", item.getString("nastnum"));// 主数量 + itemDetails.put("ftaxtypeflag", 1);// 扣税类别 + itemDetails.put("pk_group", "00");// 集团 + itemDetails.put("pk_org", originalJson.getJSONObject("billhead").getString("pk_org"));// 开票组织 + itemDetails.put("cunitid", item.getString("castunitid"));// 主单位 + itemDetails.put("vchangerate", value2.getOrDefault("vchangerate", "1/1") + "");// 换算率 + + // 从销售订单中获取币种 + String currencycode = getString_TrimAsNull(value2.get("currencycode")); + otherJson.put("corigcurrencyid", currencycode.isEmpty() ? "CNY" : currencycode); + // 从销售订单中获取折本汇率 + BigDecimal nexchangerate = getUFDouble_NullAsZero(value2.get("nexchangerate")).toBigDecimal(); + otherJson.put("nexchangerate", nexchangerate); + + // 输入参数:从你的 item 获取各个字段 + BigDecimal nastnum = new BigDecimal(item.getString("nastnum")); // 数量 + nastnum = nastnum.setScale(4, RoundingMode.HALF_UP); + BigDecimal nqtorigtaxprice = new BigDecimal(item.getString("nqtorigtaxprice")); // 含税单价 + nqtorigtaxprice = nqtorigtaxprice.setScale(4, RoundingMode.HALF_UP); + BigDecimal ntaxrate = new BigDecimal(item.getString("ntaxrate")).divide(new BigDecimal("100")); // 税率 + ntaxrate = ntaxrate.setScale(4, RoundingMode.HALF_UP); + + // 含税净价 + BigDecimal norigtaxnetprice = nqtorigtaxprice; + // 1. 计算价税合计(含税金额) + BigDecimal norigtaxmny = nastnum.multiply(norigtaxnetprice).setScale(2, RoundingMode.HALF_UP); + // 2. 计算折扣额 + BigDecimal discountAmount = nastnum.multiply(nqtorigtaxprice).subtract(norigtaxmny).setScale(4, + RoundingMode.HALF_UP); + // 3. 计算税额(两种方法:应税外加税和应税内含税) + BigDecimal ntax = norigtaxmny.multiply(ntaxrate).divide(BigDecimal.ONE.add(ntaxrate), 2, + RoundingMode.HALF_UP); // 应税外加税 + BigDecimal taxInclusiveInner = norigtaxmny.multiply(ntaxrate).setScale(4, RoundingMode.HALF_UP); // 应税内含税 + // 4. 计算无税金额 + BigDecimal norigmny = norigtaxmny.subtract(ntax).setScale(2, RoundingMode.HALF_UP); + // 4. 计算无税单价(nqtorigprice = 无税金额 / 数量) + BigDecimal nqtorigprice = norigmny.divide(nastnum, 4, RoundingMode.HALF_UP); + // 计税金额 = 无税金额 + BigDecimal ncaltaxmny = norigmny; + // 主含税单价(即含税单价) + BigDecimal norigtaxprice = nqtorigtaxprice.setScale(4, RoundingMode.HALF_UP); + // 主无税净价(即不含税单价) + BigDecimal norignetprice = nqtorigprice; + + // 本币(人民币)需要处理汇率,金额保留两位小数,单价保留4位小数 + // 本币无税金额 + BigDecimal nmny = norigmny.multiply(nexchangerate).setScale(2, RoundingMode.HALF_UP); + // 主本币无税净价 + BigDecimal nnetprice = norignetprice.multiply(nexchangerate).setScale(4, RoundingMode.HALF_UP); + // 本币价税合计 价税合计*汇率 + BigDecimal ntaxmny = norigtaxmny.multiply(nexchangerate).setScale(2, RoundingMode.HALF_UP); + // 税额 + ntax = ntaxmny.subtract(nmny).setScale(2, RoundingMode.HALF_UP); + + itemDetails.put("nqtorigprice", nqtorigprice);// 无税单价 + itemDetails.put("norigprice", nqtorigprice);// 主无税单价 + itemDetails.put("norigmny", norigmny);// 无税金额 + itemDetails.put("nmny", nmny);// 本币无税金额 + itemDetails.put("norigtaxmny", norigtaxmny);// 价税合计 + itemDetails.put("norigtaxprice", norigtaxprice);// 主含税单价 + itemDetails.put("norignetprice", norignetprice);// 主无税净价 + itemDetails.put("nqtorigtaxprice", nqtorigtaxprice);// 含税单价 + itemDetails.put("ntax", ntax);// 税额 + itemDetails.put("ncaltaxmny", ncaltaxmny);// 计税金额 + itemDetails.put("norigtaxnetprice", norigtaxnetprice);// 主含税净价 + itemDetails.put("nnetprice", nnetprice);// 主本币无税净价 + itemDetails.put("ntaxmny", ntaxmny);// 本币价税合计 + csaleinvoicebid.add(itemDetails); + + } + newItem.put("item", csaleinvoicebid); + billhead.put("csaleinvoicebid", newItem); + if (otherJson != null && !otherJson.isEmpty()) { + // 查询销售订单中的币种和汇率 + billhead.put("corigcurrencyid", otherJson.get("corigcurrencyid"));// 币种 + billhead.put("nexchangerate", otherJson.get("nexchangerate"));// 折本汇率 + } + bill.put("billhead", billhead); + bill.put("id", ""); + // 将 bill 数组添加到 ufinterface 中 + billArray.add(bill); + ufinterface.put("bill", billArray); + // 将 ufinterface 添加到最终的 resultJson 中 + resultJson.put("ufinterface", ufinterface); + return resultJson; + } catch (Exception e) { + return (JSONObject) ResultMessageUtil.exceptionToJSON(e); + } + } + + private static String getTaxcode(String taxrateStr) throws BusinessException { + IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); + String sql = " select code FROM bd_taxrate tt inner join bd_taxcode tc on tt.pk_taxcode=tc.pk_taxcode where taxrate='" + + taxrateStr + "' AND ROWNUM = 1 "; + String taxcodeStr = (String) queryBS.executeQuery(sql, new ColumnProcessor()); + return taxcodeStr; + } + + private static Map getSaleorderVo(String csourcebillbidStr) throws BusinessException { + IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); + String sql = " select s.vbillcode,s.csaleorderid, s.corigcurrencyid," + + " sb.csaleorderbid,sb.crowno,sb.blargessflag,sb.nexchangerate,sb.vchangerate," + + " bdc.code currencycode" + + " from so_saleorder_b sb" + + " inner join so_saleorder s on sb.csaleorderid=s.csaleorderid" + + " left join bd_currtype bdc on s.corigcurrencyid=bdc.pk_currtype" + + " where sb.csaleorderbid='" + csourcebillbidStr + "' "; + Map value2 = (Map) queryBS.executeQuery(sql, new MapProcessor()); + return value2; + } + + private static String getString_TrimAsNull(Object value) { + if ((value == null) || (value.toString().trim().isEmpty())) { + return ""; + } + return value.toString().trim(); + } + + private static UFDouble getUFDouble_NullAsZero(Object value) { + if ((value == null) || (value.toString().trim().isEmpty()) || (value.toString().trim().equals("~"))) + return UFDouble.ONE_DBL; + if ((value instanceof UFDouble)) + return (UFDouble) value; + if ((value instanceof BigDecimal)) { + return new UFDouble((BigDecimal) value); + } + return new UFDouble(value.toString().trim()); + } + + /** + * 构造红冲发票VO + * + * @param originalVO + * @param bject + * @return + * @throws Exception + */ + public static SaleInvoiceVO makeNewRedRushSaleInvoice(SaleInvoiceVO originalVO, JSONObject bject) throws Exception { + try { + SaleInvoiceVO saleInvoiceVO = new SaleInvoiceVO(); + // 发票主实体 + SaleInvoiceHVO saleInvoiceHVO = originalVO.getParentVO(); + // 发票子实体数组 + SaleInvoiceBVO[] saleInvoiceBVOs = originalVO.getChildrenVO(); + // 发票新主实体 + SaleInvoiceHVO newSaleInvoiceHVO = new SaleInvoiceHVO(); + + // 单据日期 + UFDate dbilldate = new UFDate(bject.getString("dbilldate")); + // 制单日期 + UFDate dmakedate = new UFDate(bject.getString("creationtime")); + + // 子实体属性赋值 + UFDouble sumNum = new UFDouble(); // 合计数量 + UFDouble sumNtax = new UFDouble(); // 合计税额 + UFDouble sumNcaltaxmny = new UFDouble(); // 合计计税金额 + UFDouble sumNorigmny = new UFDouble(); // 合计无税金额 + UFDouble sumNorigtaxmny = new UFDouble(); // 合计价税合计 + int i = 0; + // 参数子实体数组 + com.alibaba.fastjson.JSONArray bvoJsonArr = (com.alibaba.fastjson.JSONArray) bject.get("csaleinvoicebid"); + List bvoList = bvoJsonArr.toJavaList(JSONObject.class); + SaleInvoiceBVO[] newSaleInvoiceBVOs = new SaleInvoiceBVO[bvoList.size()]; // 新子实体 + for (SaleInvoiceBVO saleInvoiceBVO : saleInvoiceBVOs) { + String csaleinvoicebid = saleInvoiceBVO.getCsaleinvoicebid(); // 子表id + // 筛选参数红冲的子表集合 + List newBvoArr = bvoList.stream().filter(item -> { + String parCsaleinvoicebid = item.getString("vbdef15") + ""; // 子表id + return csaleinvoicebid.equals(parCsaleinvoicebid); + }).toList(); + if (newBvoArr.size() <= 0) { + continue; + } + JSONObject bipBvoJson = newBvoArr.get(0); // 参数子表 + SaleInvoiceBVO newInvBVO = new SaleInvoiceBVO(); + // 克隆取值原子表销售发票 + newInvBVO = (SaleInvoiceBVO) getCloneTool().deepClone(saleInvoiceBVO); + // 赋值之后修改子实体红冲时字段 + newInvBVO.setCsaleinvoicebid(null); // 发票子实体id + newInvBVO.setDbilldate(dbilldate); // 开票日期 + String vchangerate = "1/1"; // 换算率 + Map soMap = getSaleOrderInfo(bipBvoJson.getString("csrcbid")); + if (soMap != null && StringUtils.isNotEmpty(soMap.getOrDefault("vchangerate", "") + "")) { + vchangerate = soMap.get("vchangerate") + ""; // 销售订单的换算率 + } + newInvBVO.setVchangerate(vchangerate); // 换算率 + UFDouble[] vchangerateNums = HslParseUtil.parseHsl(vchangerate); + UFDouble vchangerateNum = UFDouble.ONE_DBL; + if (null != vchangerateNums && vchangerateNums.length != 0) { + vchangerateNum = vchangerateNums[0].div(vchangerateNums[1]).setScale(2, 4); + } + // BIP合同平台的数量对应BIP2312的主数量,BIP2312的 数量=主数量*换算关系 + UFDouble nastnum = new UFDouble(bipBvoJson.getString("nastnum")); + newInvBVO.setNastnum(nastnum.multiply(vchangerateNum).setScale(2, 4)); // 数量 + newInvBVO.setNnum(nastnum); // 主数量 + newInvBVO.setNtax(new UFDouble(bipBvoJson.getString("ntax"))); // 税额 + newInvBVO.setNmny(new UFDouble(bipBvoJson.getString("nmny"))); // 本币无税金额 + newInvBVO.setNtaxmny(new UFDouble(bipBvoJson.getString("ntaxmny"))); // 本币价税合计 + newInvBVO.setNcaltaxmny(new UFDouble(bipBvoJson.getString("ncaltaxmny"))); // 计税金额 + newInvBVO.setNorigmny(new UFDouble(bipBvoJson.getString("norigmny"))); // 无税金额 + newInvBVO.setNorigtaxmny(new UFDouble(bipBvoJson.getString("norigtaxmny"))); // 价税合计 + newInvBVO.setCopposesrcbid(bipBvoJson.getString("vbdef15")); // 对冲来源子表id + newInvBVO.setNqtunitnum(null); // 报价数量 + newInvBVO.setCsaleinvoiceid(null); // 发票关联主表id + newInvBVO.setNtotalcostnum(null); // 累计成本结算数量 + newInvBVO.setNtotalincomemny(null); // 累计确认应收金额 + newInvBVO.setNtotalincomenum(null); // 累计确认应收数量 + newSaleInvoiceBVOs[i++] = newInvBVO; + sumNum = sumNum.add(new UFDouble(bipBvoJson.getString("nnum"))); + sumNtax = sumNtax.add(new UFDouble(bipBvoJson.getString("ntax"))); + sumNcaltaxmny = sumNcaltaxmny.add(new UFDouble(bipBvoJson.getString("ncaltaxmny"))); + sumNorigmny = sumNorigmny.add(new UFDouble(bipBvoJson.getString("norigmny"))); + sumNorigtaxmny = sumNorigtaxmny.add(new UFDouble(bipBvoJson.getString("norigtaxmny"))); + } + + // 克隆取值原子表销售发票 + newSaleInvoiceHVO = (SaleInvoiceHVO) getCloneTool().deepClone(saleInvoiceHVO); + // 赋值之后修改主实体红冲时字段 + newSaleInvoiceHVO.setCsaleinvoiceid(null); // 发票主实体id + newSaleInvoiceHVO.setVbillcode(null); // 发票号 + newSaleInvoiceHVO.setDbilldate(dbilldate); // 开票日期 + newSaleInvoiceHVO.setDmakedate(dmakedate); // 制单日期 + newSaleInvoiceHVO.setBsubunitflag(UFBoolean.TRUE); // 冲抵标记 + newSaleInvoiceHVO.setFopposeflag(2); // 对冲标记 (2:对冲生成) + newSaleInvoiceHVO.setFstatusflag(1); // 单据状态 (1:自由态) + newSaleInvoiceHVO.setNtotalastnum(null); // 总数量 + newSaleInvoiceHVO.setNtotalorigsubmny(null); // 冲抵金额 + newSaleInvoiceHVO.setNtotalorigmny(null); // 价税合计 + newSaleInvoiceHVO.setVopposesrccode(saleInvoiceHVO.getVbillcode()); // 对冲来源发票号 + newSaleInvoiceHVO.setCopposesrcid(saleInvoiceHVO.getCsaleinvoiceid()); // 对冲来源发票id + newSaleInvoiceHVO.setApprover(null); // 审批人 + newSaleInvoiceHVO.setTaudittime(null); // 审批日期 + + // 组装VO + saleInvoiceVO.setParentVO(newSaleInvoiceHVO); + saleInvoiceVO.setChildrenVO(newSaleInvoiceBVOs); + return saleInvoiceVO; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + /** + * 构造红冲开票申请VO + * + * @param applyHeadVO 原开票申请主实体 + * @param ivApplicationBodyVOS 原开票申请子实体 + * @param bject bip参数 + * @param returnApproveSaleInvoiceVOs 新生成的红冲销售发票实体 + * @return + * @throws Exception + */ + public static IVApplicationAggVO makeNewRedRushIVApplicationAggVO(IVApplicationHeadVO applyHeadVO, IVApplicationBodyVO[] ivApplicationBodyVOS, JSONObject bject, SaleInvoiceVO[] returnApproveSaleInvoiceVOs) throws Exception { + try { + IVApplicationAggVO applicationAggVO = new IVApplicationAggVO(); + IVApplicationHeadVO newivApplicationHeadVO = new IVApplicationHeadVO(); // 新主实体 + + // 取新生成红冲发票的主实体数据 + String csaleinvoiceid = returnApproveSaleInvoiceVOs[0].getParentVO().getCsaleinvoiceid(); + String[] ids = {csaleinvoiceid}; + SaleInvoiceVO[] rpSaleInvoiceVOs = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) + .queryVOByIDs(ids); + SaleInvoiceHVO rpSaleInvoiceHVO = rpSaleInvoiceVOs[0].getParentVO(); + + // 主实体属性赋值 + // 克隆取值原子表开票申请 + newivApplicationHeadVO = (IVApplicationHeadVO) getCloneTool().deepClone(applyHeadVO); + // 根据参数判断是否为部分红冲 + boolean isPartHCFlag = false; + UFDouble paramNtotalorigmny = new UFDouble(bject.getString("ntotalorigmny")); // 参数价税合计(主表红冲金额) + UFDouble ntotalorigmny = applyHeadVO.getJshj(); // 原开票申请主表价税合计 + // 红冲金额与开票申请源价税合计比较如果和值大于零,则为部分红冲 + if (ntotalorigmny.add(paramNtotalorigmny).compareTo(UFDouble.ZERO_DBL) > 0) { + isPartHCFlag = true; + } + UFDouble sumXmsl = new UFDouble(); // 合计数量 + UFDouble sumXmje = new UFDouble(); // 合计金额 + UFDouble sumXmjshj = new UFDouble(); // 合计价税合计 + UFDouble sumBchcje = new UFDouble(); // 合计本次红冲金额 + UFDouble sumSe = new UFDouble(); // 合计税额 + // 子实体属性赋值 + int i = 0; + // 参数子实体数组 + com.alibaba.fastjson.JSONArray bvoJsonArr = (com.alibaba.fastjson.JSONArray) bject.get("csaleinvoicebid"); + List bvoList = bvoJsonArr.toJavaList(JSONObject.class); + IVApplicationBodyVO[] newivApplicationBodyVOS = new IVApplicationBodyVO[bvoList.size()]; // 新子实体 + for (IVApplicationBodyVO ivApplicationBodyVO : ivApplicationBodyVOS) { + String src_pkdetail = ivApplicationBodyVO.getSrc_pkdetail(); // 来源单据行id + // 筛选参数红冲的子表集合 + List newBvoArr = bvoList.stream().filter(item -> { + String parCsaleinvoicebid = item.getString("vbdef15") + ""; // 子表id + return src_pkdetail.equals(parCsaleinvoicebid); + }).toList(); + if (newBvoArr.size() <= 0) { + continue; + } + JSONObject bipBvoJson = newBvoArr.get(0); // 参数子表 + IVApplicationBodyVO newivApplicationBodyVO = new IVApplicationBodyVO(); +// BeanUtil.copyProperties(ivApplicationBodyVO,newivApplicationBodyVO, CopyOptions.create().setIgnoreNullValue(true)); + // 克隆取值原子表开票申请 + newivApplicationBodyVO = (IVApplicationBodyVO) getCloneTool().deepClone(ivApplicationBodyVO); + // 赋值之后修改子实体红冲时字段 + newivApplicationBodyVO.setPk_ivappdetail(null); // 开票申请子实体id + newivApplicationBodyVO.setBillno(null); // 开票申请子实体单据号 + newivApplicationBodyVO.setSe(new UFDouble(bipBvoJson.getString("ntax"))); // 税额 + newivApplicationBodyVO.setXmsl(new UFDouble(bipBvoJson.getString("nnum"))); // 数量 + newivApplicationBodyVO.setXmje(new UFDouble(bipBvoJson.getString("norigmny"))); // 金额 + newivApplicationBodyVO.setXmjshj(new UFDouble(bipBvoJson.getString("norigtaxmny"))); // 价税合计 + // 本次红冲金额 = 本次参数红冲金额 + newivApplicationBodyVO.setBchcje(new UFDouble(bipBvoJson.getString("norigtaxmny")).multiply(new UFDouble(-1))); + newivApplicationBodyVOS[i++] = newivApplicationBodyVO; + sumSe = sumSe.add(new UFDouble(bipBvoJson.getString("ntax"))); + sumXmsl = sumXmsl.add(new UFDouble(bipBvoJson.getString("nnum"))); + sumXmje = sumXmje.add(new UFDouble(bipBvoJson.getString("norigmny"))); + sumXmjshj = sumXmjshj.add(new UFDouble(bipBvoJson.getString("norigtaxmny"))); + sumBchcje = sumBchcje.add(new UFDouble(bipBvoJson.getString("norigtaxmny")).multiply(new UFDouble(-1))); + } + // 赋值之后修改主实体红冲时字段 + newivApplicationHeadVO.setPk_ivapplication(null); // 开票申请单主实体id + newivApplicationHeadVO.setBillno(null); // 单据号 + newivApplicationHeadVO.setPreparedate(new UFDate(bject.getString("dbilldate"))); // 单据日期 + newivApplicationHeadVO.setJshj(sumXmjshj); // 价税合计 + newivApplicationHeadVO.setHjje(sumXmje); // 合计金额 + newivApplicationHeadVO.setHjse(sumSe); // 合计税额 + newivApplicationHeadVO.setBchcje(sumBchcje); // 本次红冲金额 + newivApplicationHeadVO.setHzfp(UFBoolean.TRUE); // 红字发票 + newivApplicationHeadVO.setSrc_billtype(SOBillType.Invoice.getCode()); // 来源单据类型 + newivApplicationHeadVO.setSrc_tradetype(rpSaleInvoiceHVO.getCtrantypeid()); // 来源交易类型 + newivApplicationHeadVO.setTranstypecode(rpSaleInvoiceHVO.getVtrantypecode()); // 来源交易类型编码 + newivApplicationHeadVO.setSrc_pkbusibill(rpSaleInvoiceHVO.getCsaleinvoiceid()); // 来源单据id + newivApplicationHeadVO.setSrc_billno(rpSaleInvoiceHVO.getVbillcode()); // 来源单据编号 + newivApplicationHeadVO.setHcyy("2"); // 红冲原因:2(开票有误) + + // 组装VO + applicationAggVO.setParentVO(newivApplicationHeadVO); + applicationAggVO.setChildrenVO(newivApplicationBodyVOS); + return applicationAggVO; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + + private static Map getSaleOrderInfo(String csaleorderbid) throws BusinessException { + IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); + String sql = " select s.vbillcode,s.csaleorderid, s.corigcurrencyid," + + " sb.csaleorderbid,sb.crowno,sb.blargessflag,sb.nexchangerate," + + " nvl(sb.vchangerate, '1/1') vchangerate, bdc.code currencycode" + + " from so_saleorder_b sb" + + " inner join so_saleorder s on sb.csaleorderid=s.csaleorderid" + + " left join bd_currtype bdc on s.corigcurrencyid=bdc.pk_currtype" + + " where sb.csaleorderbid='" + csaleorderbid + "' "; + return (Map) queryBS.executeQuery(sql, new MapProcessor()); + } + +} diff --git a/so/src/public/nccloud/api/so/saleinvoice/operator/SaleInvResource.java b/so/src/public/nccloud/api/so/saleinvoice/operator/SaleInvResource.java new file mode 100644 index 00000000..be925c78 --- /dev/null +++ b/so/src/public/nccloud/api/so/saleinvoice/operator/SaleInvResource.java @@ -0,0 +1,76 @@ +package nccloud.api.so.saleinvoice.operator; + +import com.alibaba.fastjson.JSONObject; +import nc.bs.logging.Logger; +import nccloud.api.rest.utils.ResultMessageUtil; +import nccloud.ws.rest.resource.AbstractNCCRestResource; +import org.json.JSONString; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +/** + * 销售发票接口适配2005代码 + * zhangxinah + */ +@Path("so/saleinvoice/operator") +public class SaleInvResource extends AbstractNCCRestResource { + + public SaleInvResource() { + } + + @Override + public String getModule() { + return "so"; + } + + @POST + @Path("saveCommit") + @Consumes({"application/json"}) + @Produces({"application/json"}) + public JSONString saveCommit(JSONString json) { + try { + JSONObject jobject = JSONObject.parseObject(json.toJSONString()); + if (jobject == null) { + return ResultMessageUtil.exceptionToJSON(new NullPointerException("JSONString:null")); + } + JSONObject bject = jobject.getJSONObject("billhead"); + if (bject == null) { + return ResultMessageUtil.exceptionToJSON(new NullPointerException("billhead:null")); + } + IAPISaleInvMaitainImpl service = new IAPISaleInvMaitainImpl(); + return service.saveBlue(jobject); + } catch (Exception e) { + Logger.error("saveCommit-exp: ", e); + return ResultMessageUtil.exceptionToJSON(e); + } + } + + /** + * 销售发票红冲接口 + * + * @author lj + * @date 2025/03/14 + * @update 20250415 mzr修改 + */ + @POST + @Path("billSaveRp") + @Consumes({"application/json"}) + @Produces({"application/json"}) + public JSONString billSaveRp(JSONString json) { + try { + JSONObject jobject = JSONObject.parseObject(json.toJSONString()); + if (jobject == null) { + return ResultMessageUtil.exceptionToJSON(new NullPointerException("JSONString:null")); + } + IAPISaleInvMaitainImpl service = new IAPISaleInvMaitainImpl(); + return service.saveRed(jobject); + } catch (Exception e) { + Logger.error("billSaveRp-exp: ", e); + return ResultMessageUtil.exceptionToJSON(e); + } + } + +} \ No newline at end of file diff --git a/so/src/public/nccloud/api/so/saleinvoice/operator/saveCommitAction.java b/so/src/public/nccloud/api/so/saleinvoice/operator/saveCommitAction.java deleted file mode 100644 index b721579e..00000000 --- a/so/src/public/nccloud/api/so/saleinvoice/operator/saveCommitAction.java +++ /dev/null @@ -1,431 +0,0 @@ -package nccloud.api.so.saleinvoice.operator; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import nc.bs.framework.common.InvocationInfoProxy; -import nc.bs.framework.common.NCLocator; -import nc.bs.framework.core.util.ObjectCreator; -import nc.itf.uap.IUAPQueryBS; -import nc.jdbc.framework.processor.ColumnProcessor; -import nc.jdbc.framework.processor.MapProcessor; -import nc.pubitf.so.m32.api.ISaleinvoiceQueryAPI; -import nc.vo.pub.BusinessException; -import nc.vo.pub.lang.UFDouble; -import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill; -import nc.vo.pubapp.pflow.PfUserObject; -import nc.vo.so.m32.entity.SaleInvoiceHVO; -import nc.vo.so.m32.entity.SaleInvoiceVO; -import nccloud.api.baseapp.exchange.convert.IExchangeForService; -import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataObject; -import nccloud.api.baseapp.exchange.convert.OpenApiConvertDataResult; -import nccloud.api.rest.utils.ResultMessageUtil; -import nccloud.dto.scmpub.script.entity.SCMScriptResultDTO; -import nccloud.pubitf.riart.pflow.CloudPFlowContext; -import nccloud.pubitf.scmpub.commit.service.IBatchRunScriptService; -import nccloud.pubitf.scmpub.ssc.service.ISSCService; -import nccloud.pubitf.so.saleinvoice.service.ISaleInvoiceToTaxInvService; -import nccloud.pubitf.ssctp.sscbd.lientage.ISSClientageMatchService.BusiUnitTypeEnum; -import nccloud.ws.rest.resource.AbstractNCCRestResource; -import org.json.JSONString; - -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Map; - -/** - * 销售发票接口适配2005代码 - * zhangxinah - */ -@Path("so/saleinvoice/operator") -public class saveCommitAction extends AbstractNCCRestResource { - - public static String fplxStr = "";// 开票申请发票类型 - - public saveCommitAction() { - - } - - public OpenApiConvertDataResult changeToExchangeData(OpenApiConvertDataObject openApiConvertDataObject) - throws Exception { - return getPFxxEJBService().changeToExchangeData(openApiConvertDataObject); - } - - public static IExchangeForService getPFxxEJBService() { - IExchangeForService exchangeForService = (IExchangeForService) ObjectCreator.newInstance("ufesbexpress", - "nccloud.pubimpl.pfxx.convert.ExchangeForServiceImpl"); - return exchangeForService; - } - - @Override - public String getModule() { - return "so"; - } - - @POST - @Path("/saveCommit") - @Consumes({"application/json"}) - @Produces({"application/json"}) - public JSONString saveCommit(JSONString json) throws Exception { - JSONObject jobject = JSONObject.parseObject(json.toJSONString()); - if (jobject == null) { - return ResultMessageUtil.exceptionToJSON(new NullPointerException("JSONString:null")); - } else { - JSONObject bject = jobject.getJSONObject("billhead"); - if (bject == null) { - return ResultMessageUtil.exceptionToJSON(new NullPointerException("billhead:null")); - } else { - - JSONObject ufinterfaceObj = jsonObjectAss(jobject); - String tsType = ufinterfaceObj.getString("tsType"); - if (tsType != null && tsType.equals("1")) { - Exception e = new NullPointerException("销售订单查询关联失败!"); - return ResultMessageUtil.exceptionToJSON(e); - } - JSONObject bjects = ufinterfaceObj.getJSONObject("ufinterface"); - String billtype = bjects.getString("billtype"); - String account = bjects.getString("account"); - String omscode = bjects.getString("orgcode"); - String groupcode = bjects.getString("groupcode"); - - if (billtype != null && account != null && groupcode != null && "32".equals(billtype)) { - OpenApiConvertDataObject openApiconvertData0bject = new OpenApiConvertDataObject(); - openApiconvertData0bject.setAccount(account); - openApiconvertData0bject.setBilltype(billtype); - openApiconvertData0bject.setGroupcode(groupcode); - openApiconvertData0bject.setOpenApiJsonData(ufinterfaceObj); - try { - OpenApiJsonConvertToExChangeXmlService oService = new OpenApiJsonConvertToExChangeXmlService(); - OpenApiConvertDataResult r = oService.changeToExchangeData(openApiconvertData0bject); - JSONObject returnJson = r.getDesc(); - String content = ""; - // 逐层解析 JSON 数据 - JSONObject ufinterface = returnJson.getJSONObject("ufinterface"); - if (ufinterface != null) { - JSONArray sendResultArray = ufinterface.getJSONArray("sendresult"); - if (sendResultArray != null && sendResultArray.size() > 0) { - // 提取 content 字段 - content = sendResultArray.getJSONObject(0).getString("content"); - } - } - if (content == null || content.equals("")) { - return r != null ? ResultMessageUtil.toJSON(r.getDesc(), "0") - : ResultMessageUtil.exceptionToJSON(new NullPointerException("未知异常")); - } - String[] ids = {content}; - SaleInvoiceVO[] saleInvoiceVO = NCLocator.getInstance().lookup(ISaleinvoiceQueryAPI.class) - .queryVOByIDs(ids); - SaleInvoiceVO saleInvoiceVO22 = saleInvoiceVO[0]; - SaleInvoiceHVO saleInvoiceHVO = saleInvoiceVO22.getParentVO(); - // 销售发票审核开始 - InvocationInfoProxy.getInstance().setUserId(saleInvoiceHVO.getApprover()); - CloudPFlowContext context = new CloudPFlowContext(); - context.setBillType("32"); - context.setBillVos(new SaleInvoiceVO[]{saleInvoiceVO[0]}); - ISSCService sscService = (ISSCService) NCLocator.getInstance().lookup(ISSCService.class); - String[] actionNames = sscService.isStartSSCWorkFlow( - (AbstractBill[]) ((AbstractBill[]) context.getBillVos()), BusiUnitTypeEnum.SO); - context.setActionName("APPROVE"); - context.setTrantype("32-02"); - context.setBatch(false); - context.setBatchUserObj(new PfUserObject[]{new PfUserObject()}); - IBatchRunScriptService service = (IBatchRunScriptService) NCLocator.getInstance() - .lookup(IBatchRunScriptService.class); - SCMScriptResultDTO result = service.runBacth(context, SaleInvoiceVO.class); - // 销售发票审核结束 - ISaleInvoiceToTaxInvService invoiceService = NCLocator.getInstance() - .lookup(ISaleInvoiceToTaxInvService.class); - // 数电票(增值税专用发票)=31,数电票(普通发票)=32,数电纸质发票(机动车销售统一发票)=36,数电纸质发票(增值税专用发票)=33,数电纸质发票(普通发票)=34, - // 增值税电子普通发票=1,增值税电子专用发票=2,增值税普通发票=3,增值税专用发票=4,增值税电子普通发票(成品油)=8,成品油普通发票(卷式)=9, - // 成品油普通发票=10,成品油专用发票=11,增值税普通发票(卷式)=12,增值税专用发票(机动车)=99 - invoiceService.issueTaxInvoice(saleInvoiceVO, fplxStr); - - JSONObject desc = r.getDesc(); - if (desc != null) { - // 发票的全部信息都返回给合同平台 - desc.put("vos", saleInvoiceVO); - } - return ResultMessageUtil.toJSON(desc, "0"); - } catch (Exception e) { - return ResultMessageUtil.exceptionToJSON(e); - } - } else { - Exception e = new NullPointerException( - "billtype:" + billtype + ",account:" + account + ",groupcode:" + groupcode); - return ResultMessageUtil.exceptionToJSON(e); - } - - } - } - } - - public static JSONObject jsonObjectAss(JSONObject originalJson) throws Exception { - try { - // 构建目标 JSON 格式 - JSONObject resultJson = new JSONObject(); - // 添加 ufinterface 字段 - JSONObject ufinterface = new JSONObject(); - ufinterface.put("billtype", "32"); - ufinterface.put("sender", "BIP_NC"); - ufinterface.put("level", "0"); - ufinterface.put("replace", "Y"); - ufinterface.put("roottag", "bill"); - ufinterface.put("isexchange", "Y"); - ufinterface.put("account", "01"); - ufinterface.put("groupcode", "00"); - // 处理 bill 数组 - JSONArray billArray = new JSONArray(); - JSONObject bill = new JSONObject(); - // billhead 结构 - JSONObject billhead = new JSONObject(); - billhead = originalJson.getJSONObject("billhead");// 传入JSON对象 - billhead.put("pk_org_v", originalJson.getJSONObject("billhead").getString("pk_org"));// 开票组织版本=开票组织 - billhead.put("pk_group", "00");// 集团 - fplxStr = originalJson.getJSONObject("billhead").getString("vdef22"); - billhead.put("vtrantypecode", "32-02");// 发票类型编码 - billhead.put("cbiztypeid", "SO01");// 业务流程 - billhead.put("approver", "BIP");// 审批人 - billhead.put("fstatusflag", 1);// 单据状态 - billhead.put("billmaker", "BIP");// 制单人 - billhead.put("csendcountryid", "CN");// 发货国家 - billhead.put("crececountryid", "CN");// 收货国家 - billhead.put("ctaxcountryid", "CN");// 报税国家 - // 2025-2-8付业要求修改,根据发票类型Q(自定义档案)对照发票类型 - String ctrantypeidStr = "32-02";// 默认普通发票 - if (fplxStr != null && fplxStr.equals("31")) { - ctrantypeidStr = "32-01";// 数电票(增值税专用发票) - } else if (fplxStr != null && fplxStr.equals("32")) { - ctrantypeidStr = "32-02";// 数电票(普通发票) - } else if (fplxStr != null && fplxStr.equals("36")) { - ctrantypeidStr = "32-Cxx-03";// 机动车销售发票 - } - billhead.put("ctrantypeid", ctrantypeidStr);// 发票类型 - // billhead.put("ctrantypeid", "32-02");//发票类型 - billhead.put("fbuysellflag", "1");// 购销类型 - billhead.put("creator", "BIP");// 创建人 - billhead.put("ccurrencyid", "CNY");// 本位币 - billhead.put("corigcurrencyid", "CNY");// 币种 - billhead.put("nexchangerate", 1);// 折本汇率 - billhead.put("btriatradeflag", 0);// 三角贸易 - JSONObject newItem = new JSONObject(); - JSONObject otherJson = new JSONObject(); - JSONArray csaleinvoicebid = new JSONArray(); - // 遍历原始数据中的 csaleinvoicebid 数组 - for (int i = 0; i < originalJson.getJSONObject("billhead").getJSONArray("csaleinvoicebid").size(); i++) { - JSONObject item = originalJson.getJSONObject("billhead").getJSONArray("csaleinvoicebid") - .getJSONObject(i); - - JSONObject itemDetails = new JSONObject(); - itemDetails = item; - itemDetails.put("carorgid", originalJson.getJSONObject("billhead").getString("pk_org"));// 应收组织 - itemDetails.put("csendstockorgid", originalJson.getJSONObject("billhead").getString("pk_org"));// 库存组织原始版本 - itemDetails.put("cmaterialid", item.getString("cmaterialvid"));// 物料编码 - Map value2 = getSaleorderVo(item.getString("csrcbid")); - if (value2 == null) { - resultJson = new JSONObject(); - resultJson.put("tsType", "1"); - return resultJson; - } - itemDetails.put("vfirsttype", "30");// 源头单据类型 - itemDetails.put("vfirstcode", value2.get("vbillcode"));// 源头单据号 - itemDetails.put("blargessflag", value2.get("blargessflag"));// 赠品 - itemDetails.put("vfirsttrantype", "30-01");// 源头交易类型 - itemDetails.put("vfirstrowno", value2.get("crowno"));// 源头单据行号 - itemDetails.put("cfirstid", item.getString("csrcid"));// 源头单据主表 - itemDetails.put("cfirstbid", item.getString("csrcbid"));// 源头单据子表 - itemDetails.put("vsrctype", "30");// 来源单据类型 - itemDetails.put("vsrccode", value2.get("vbillcode"));// 来源单据号 - itemDetails.put("vsrctrantype", "30-01");// 来源交易类型 - itemDetails.put("vsrcrowno", value2.get("crowno"));// 来源单据行号 - // 通过 ntaxrate 获取 taxcode - String taxcodeStr = getTaxcode(item.getString("ntaxrate")); - // 将 taxcodeStr 放入 bodyMap - itemDetails.put("ctaxcodeid", taxcodeStr);// 税码 - itemDetails.put("nnum", item.getString("nastnum"));// 主数量 - itemDetails.put("ftaxtypeflag", 1);// 扣税类别 - itemDetails.put("pk_group", "00");// 集团 - itemDetails.put("pk_org", originalJson.getJSONObject("billhead").getString("pk_org"));// 开票组织 - itemDetails.put("cunitid", item.getString("castunitid"));// 主单位 - itemDetails.put("vchangerate", value2.getOrDefault("vchangerate", "1/1") + "");// 换算率 - -// double nastnum = Double.parseDouble(item.getString("nastnum"));//数量 -// double nqtorigtaxprice = Double.parseDouble(item.getString("nqtorigtaxprice"));//含税单价 -// double ntaxrate = Double.parseDouble(item.getString("ntaxrate"));//税率 -// -// double nqtorigprice = -// Math.round(nqtorigtaxprice / (1 + ntaxrate) * 100.0) / 100.0;//不含税单价、无税单价(含税单价/(1+税率)) -// double norigmny = Math.round(nqtorigprice * nastnum * 100.0) / 100.0;//无税金额(不含税单价*数量) -// double norigtaxmny = Math.round(nastnum * nqtorigtaxprice * 100.0) / 100.0;//价税合计、含税金额(数量*含税单价) -// double norigtaxprice = Math.round(nqtorigtaxprice * 100.0) / 100.0;//主含税单价(含税单价) -// double norignetprice = nqtorigprice;//主无税净价(不含税单价) -// double ntax = Math.round(norigtaxmny / (1 + ntaxrate) * ntaxrate * 100.0) / 100.0;//税额(含税金额/(1+税率)*税率) -// double ncaltaxmny = norigmny;//计税金额(无税金额) -// double norigtaxnetprice = norigtaxprice;//主含税净价(主含税单价) - -// BigDecimal nastnum = new BigDecimal(item.getString("nastnum"));//数量 -// BigDecimal nqtorigtaxprice = new BigDecimal(item.getString("nqtorigtaxprice"));//含税单价 -// BigDecimal ntaxrate = new BigDecimal(item.getString("ntaxrate"));//税率 -// -// // 1. 计算不含税单价 -// BigDecimal nqtorigprice = nqtorigtaxprice.divide(BigDecimal.ONE.add(ntaxrate), 4, RoundingMode.HALF_UP); -// // 2. 计算无税金额 = 不含税单价 * 数量 -// BigDecimal norigmny = nqtorigprice.multiply(nastnum).setScale(4, RoundingMode.HALF_UP); -// // 3. 计算税额 = 无税金额 * 税率 -// BigDecimal ntax = norigmny.multiply(ntaxrate).setScale(4, RoundingMode.HALF_UP); -// // 4. 计算含税金额 = 无税金额 + 税额 -// BigDecimal norigtaxmny = norigmny.add(ntax).setScale(4, RoundingMode.HALF_UP); -// // 主含税单价(即含税单价) -// BigDecimal norigtaxprice = nqtorigtaxprice.setScale(4, RoundingMode.HALF_UP); -// // 主无税净价(即不含税单价) -// BigDecimal norignetprice = nqtorigprice; -// // 计税金额 = 无税金额 -// BigDecimal ncaltaxmny = norigmny; -// // 主含税净价 = 含税单价(原始) -// BigDecimal norigtaxnetprice = norigtaxprice; - - // 从销售订单中获取币种 - String currencycode = getString_TrimAsNull(value2.get("currencycode")); - otherJson.put("corigcurrencyid", currencycode.isEmpty() ? "CNY" : currencycode); - // 从销售订单中获取折本汇率 - BigDecimal nexchangerate = getUFDouble_NullAsZero(value2.get("nexchangerate")).toBigDecimal(); - otherJson.put("nexchangerate", nexchangerate); - - // 输入参数:从你的 item 获取各个字段 - BigDecimal nastnum = new BigDecimal(item.getString("nastnum")); // 数量 - nastnum = nastnum.setScale(4, RoundingMode.HALF_UP); - BigDecimal nqtorigtaxprice = new BigDecimal(item.getString("nqtorigtaxprice")); // 含税单价 - nqtorigtaxprice = nqtorigtaxprice.setScale(4, RoundingMode.HALF_UP); - BigDecimal ntaxrate = new BigDecimal(item.getString("ntaxrate")).divide(new BigDecimal("100")); // 税率 - ntaxrate = ntaxrate.setScale(4, RoundingMode.HALF_UP); - - // 含税净价 - BigDecimal norigtaxnetprice = nqtorigtaxprice; - // 1. 计算价税合计(含税金额) - BigDecimal norigtaxmny = nastnum.multiply(norigtaxnetprice).setScale(2, RoundingMode.HALF_UP); - // 2. 计算折扣额 - BigDecimal discountAmount = nastnum.multiply(nqtorigtaxprice).subtract(norigtaxmny).setScale(4, - RoundingMode.HALF_UP); - // 3. 计算税额(两种方法:应税外加税和应税内含税) - BigDecimal ntax = norigtaxmny.multiply(ntaxrate).divide(BigDecimal.ONE.add(ntaxrate), 2, - RoundingMode.HALF_UP); // 应税外加税 - BigDecimal taxInclusiveInner = norigtaxmny.multiply(ntaxrate).setScale(4, RoundingMode.HALF_UP); // 应税内含税 - // 4. 计算无税金额 - BigDecimal norigmny = norigtaxmny.subtract(ntax).setScale(2, RoundingMode.HALF_UP); - // 4. 计算无税单价(nqtorigprice = 无税金额 / 数量) - BigDecimal nqtorigprice = norigmny.divide(nastnum, 4, RoundingMode.HALF_UP); - // 计税金额 = 无税金额 - BigDecimal ncaltaxmny = norigmny; - // 主含税单价(即含税单价) - BigDecimal norigtaxprice = nqtorigtaxprice.setScale(4, RoundingMode.HALF_UP); - // 主无税净价(即不含税单价) - BigDecimal norignetprice = nqtorigprice; - - // 本币(人民币)需要处理汇率,金额保留两位小数,单价保留4位小数 - // 本币无税金额 - BigDecimal nmny = norigmny.multiply(nexchangerate).setScale(2, RoundingMode.HALF_UP); - // 主本币无税净价 - BigDecimal nnetprice = norignetprice.multiply(nexchangerate).setScale(4, RoundingMode.HALF_UP); - // 本币价税合计 价税合计*汇率 - BigDecimal ntaxmny = norigtaxmny.multiply(nexchangerate).setScale(2, RoundingMode.HALF_UP); - // 税额 - ntax = ntaxmny.subtract(nmny).setScale(2, RoundingMode.HALF_UP); - - itemDetails.put("nqtorigprice", nqtorigprice);// 无税单价 - itemDetails.put("norigprice", nqtorigprice);// 主无税单价 - itemDetails.put("norigmny", norigmny);// 无税金额 - itemDetails.put("nmny", nmny);// 本币无税金额 - itemDetails.put("norigtaxmny", norigtaxmny);// 价税合计 - itemDetails.put("norigtaxprice", norigtaxprice);// 主含税单价 - itemDetails.put("norignetprice", norignetprice);// 主无税净价 - itemDetails.put("nqtorigtaxprice", nqtorigtaxprice);// 含税单价 - itemDetails.put("ntax", ntax);// 税额 - itemDetails.put("ncaltaxmny", ncaltaxmny);// 计税金额 - itemDetails.put("norigtaxnetprice", norigtaxnetprice);// 主含税净价 - itemDetails.put("nnetprice", nnetprice);// 主本币无税净价 - itemDetails.put("ntaxmny", ntaxmny);// 本币价税合计 - csaleinvoicebid.add(itemDetails); - - } - newItem.put("item", csaleinvoicebid); - billhead.put("csaleinvoicebid", newItem); - if (otherJson != null && !otherJson.isEmpty()) { - // 查询销售订单中的币种和汇率 - billhead.put("corigcurrencyid", otherJson.get("corigcurrencyid"));// 币种 - billhead.put("nexchangerate", otherJson.get("nexchangerate"));// 折本汇率 - } - bill.put("billhead", billhead); - bill.put("id", ""); - // 将 bill 数组添加到 ufinterface 中 - billArray.add(bill); - ufinterface.put("bill", billArray); - // 将 ufinterface 添加到最终的 resultJson 中 - resultJson.put("ufinterface", ufinterface); - return resultJson; - } catch (Exception e) { - return (JSONObject) ResultMessageUtil.exceptionToJSON(e); - } - } - - // 方法:检查必填项并返回转化后的Map - public static String checkRequiredFields(JSONObject data) throws Exception { - String returnStr = ""; - // 2. 检查必填字段 pk_org - String pkOrg = (String) data.getOrDefault("pk_org", ""); - if (pkOrg.isEmpty()) { - return "字段pk_org缺失或为空!"; - } - // 2. 检查必填字段 pk_org - String vbillcode = (String) data.getOrDefault("vbillcode", ""); - if (vbillcode.isEmpty()) { - return "字段vbillcode缺失或为空!"; - } - return returnStr; - } - - private static String getTaxcode(String taxrateStr) throws BusinessException { - IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); - String sql = " select code FROM bd_taxrate tt inner join bd_taxcode tc on tt.pk_taxcode=tc.pk_taxcode where taxrate='" - + taxrateStr + "' AND ROWNUM = 1 "; - String taxcodeStr = (String) queryBS.executeQuery(sql, new ColumnProcessor()); - return taxcodeStr; - } - - private static Map getSaleorderVo(String csourcebillbidStr) throws BusinessException { - IUAPQueryBS queryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class); - String sql = " select s.vbillcode,s.csaleorderid, s.corigcurrencyid," + - " sb.csaleorderbid,sb.crowno,sb.blargessflag,sb.nexchangerate,sb.vchangerate," + - " bdc.code currencycode" + - " from so_saleorder_b sb" + - " inner join so_saleorder s on sb.csaleorderid=s.csaleorderid" + - " left join bd_currtype bdc on s.corigcurrencyid=bdc.pk_currtype" + - " where sb.csaleorderbid='" + csourcebillbidStr + "' "; - Map value2 = (Map) queryBS.executeQuery(sql, new MapProcessor()); - return value2; - } - - private static String getString_TrimAsNull(Object value) { - if ((value == null) || (value.toString().trim().isEmpty())) { - return ""; - } - return value.toString().trim(); - } - - private static UFDouble getUFDouble_NullAsZero(Object value) { - if ((value == null) || (value.toString().trim().isEmpty()) || (value.toString().trim().equals("~"))) - return UFDouble.ONE_DBL; - if ((value instanceof UFDouble)) - return (UFDouble) value; - if ((value instanceof BigDecimal)) { - return new UFDouble((BigDecimal) value); - } - return new UFDouble(value.toString().trim()); - } - - public IUAPQueryBS getQueryService() { - return NCLocator.getInstance().lookup(IUAPQueryBS.class); - } - -} \ No newline at end of file