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