Browse Source

【英唐电子发票】

wuyx 2 years ago
parent
commit
358c47d8b7

+ 8 - 0
src/main/java/com/uas/eis/controller/ERPController.java

@@ -47,4 +47,12 @@ public class ERPController {
     public Map<String, Object> cancelInvoiceOrder(String master, Integer id){
         return erpService.cancelInvoiceOrder(master,id);
     }
+
+    /**
+     * 开票订单-获取发票
+     */
+    @RequestMapping("/erp/getElecInvoicesById")
+    public Map<String, Object> getElecInvoices(String master, Integer id){
+        return erpService.getElecInvoicesById(master,id);
+    }
 }

+ 23 - 0
src/main/java/com/uas/eis/dao/BaseNuoNuoResp.java

@@ -0,0 +1,23 @@
+package com.uas.eis.dao;
+
+
+public class BaseNuoNuoResp {
+    private String status;
+    private String message;
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 97 - 0
src/main/java/com/uas/eis/dto/FindOrderRelationInvoiceDTO.java

@@ -0,0 +1,97 @@
+package com.uas.eis.dto;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class FindOrderRelationInvoiceDTO {
+    private String sid;//发票流水号,返回合并冲销的开票单为空
+    private String orderNo;//开票单号
+    private String createtime;//开票单的创建时间
+    private Number invoiceType;//发票类型,合并冲销时为空;1:蓝票 2:红票
+    private String invoiceLine;//发票种类,合并冲销时为空 p:普通发票(电票) c:普通发票(纸票) s:专用发票(纸票) b:专用发票(电子) e:收购发票(电票) f:收购发票(纸质) r:普通发票(卷式) bs:数电专票(电子) pc:数电普票(电子) es:数电专票(纸质) ec:数电普票(纸质)
+    private String specificFactor;//1 成品油、35 矿产品;普通发票为空
+    private Number invoiceState;//开票状态,合并冲销时为空 1:开票成功 2:开票失败
+    private String exceptionMessage;//开票异常信息,开票失败状态时返回
+    private String invoiceCode;//发票代码,仅开票成功会返回,发票种类为bs和pc时为空
+    private String invoiceNumber;//发票号码,仅开票成功会返回,发票种类为bs和pc时为空
+    private String allElectronicInvoiceNumber;//数电发票号码,仅数电发票开票成功会返回
+    private String oldInvoiceCode;//原发票代码(红字发票开票成功后若有值回传),发票种类为bs和pc时为空
+    private String oldInvoiceNumber;//原发票号码(红字发票开票成功后若有值回传),发票种类为bs和pc时为空
+    private String oldAllElectronicInvoiceNu;//原数电发票号码(数电发票开票成功后若有值回传)
+    private String invoiceTime;//开票日期,仅开票成功会返回
+    private String invalidTime;//作废日期,暂时未用到
+    private String rushRedState;//发票冲红状态(0 未冲红,1 全部冲红,2 部分冲红)
+    private String pdfUrl;//发票pdf地址,仅开票成功时返回
+    private String ofdUrl;//发票ofd地址,仅开票成功时返回
+    private String imageUrl;//发票jpg地址,仅开票成功时返回
+    private Number calcExcludingTaxAmount;//不含税金额,开票失败时不返回,含税金额和不含税金额任一数值返回为0,即为合并冲销
+    private Number calcTaxAmount;//税额,开票失败时不返回
+    private Number caleOrderAmount;//含税金额,开票失败时不返回,含税金额和不含税金额任一数值返回为0,即为合并冲销
+    private String sellerTaxNo;//销方税号
+    private String sellerName;//销方名称,仅开票成功会返回
+    private String taxNo;//购方税号,仅开票成功会返回
+    private String buyerName;//购方名称,仅开票成功会返回
+    private String remark;//发票备注
+    private String clerker;//开票员
+    private String payee;//收款人
+    private String checker;//复核人
+    private String clerkId;//所属开票员id
+    private String deptId;//所属部门id
+    private String bField1;//主表自定义字段1
+    private String bField2;//主表自定义字段2
+    private String bField3;//主表自定义字段3
+    private List<OrderDetailCallBackVOSDTO> orderDetailCallBackVOS;//发票来源的订单明细list
+    private List<RelateRedInvoiceDTO> relateRedInvoiceList;//发票来源的订单明细list
+
+    public String toMergeSql(int ioid,int detno){
+        String sql = "merge into (" +
+                "    select ei_id,ei_indate,ei_updatedate,ei_detno,ei_ioid,ei_iocode,ei_biid,ei_bicode " +
+                "        ,ei_sid,ei_orderno,ei_createtime,ei_invoicetype,ei_invoiceline,ei_specificfactor,ei_invoicestate,ei_exceptionmessage,ei_invoicecode,ei_invoicenumber " +
+                "        ,ei_allelectronicinvoicenumber,ei_oldinvoicecode,ei_oldinvoicenumber,ei_oldallelectronicinvoicenu,ei_invoicetime,ei_invalidtime,ei_rushredstate,ei_pdfurl,ei_ofdurl " +
+                "        ,ei_imageurl,ei_calcexcludingtaxamount,ei_calctaxamount,ei_caleorderamount,ei_sellertaxno,ei_sellername,ei_taxno,ei_buyername,ei_remark,ei_clerker " +
+                "        ,ei_payee,ei_checker,ei_bfield1,ei_bfield2,ei_bfield3 " +
+                "    from elecinvoice where ei_ioid = " +ioid+
+                " ) a USING ( " +
+                "    select io_id,io_code,io_biid,io_bicode, "+detno+" eiDetno " +
+                "        ,"+stringField(getSid())+" eiSid,"+stringField(getOrderNo())+" eiOrderno,"+timeField(getCreatetime())+" eiCreatetime,"+numberField(getInvoiceType())+" eiInvoicetype,"+stringField(getInvoiceLine())+" eiinvoiceline,"+stringField(getSpecificFactor())+" eiSpecificfactor,"+numberField(getInvoiceState())+" eiInvoicestate" +
+                "        ,"+stringField(getExceptionMessage())+" eiExceptionmessage,"+stringField(getInvoiceCode())+" eiInvoicecode,"+stringField(getInvoiceNumber())+" eiInvoicenumber " +
+                "        ,"+stringField(getAllElectronicInvoiceNumber())+" eiAllelectronicinvoicenumber,"+stringField(getOldInvoiceCode())+" eiOldinvoicecode,"+stringField(getOldInvoiceNumber())+" eiOldinvoicenumber,"+stringField(getOldAllElectronicInvoiceNu())+" eiOldallelectronicinvoicenu " +
+                "        ,"+timeField(getInvoiceTime())+" eiInvoicetime,"+timeField(getInvalidTime())+" eiInvalidtime,"+(getRushRedState())+" eiRushredstate " +
+                "        ,"+stringField(getPdfUrl())+" eiPdfurl,"+stringField(getOfdUrl())+" eiOfdurl,"+stringField(getImageUrl())+" eiImageurl,"+numberField(getCalcExcludingTaxAmount())+" eiCalcexcludingtaxamount,"+numberField(getCalcTaxAmount())+" eiCalctaxamount,"+numberField(getCaleOrderAmount())+" eiCaleorderamount" +
+                "        ,"+stringField(getSellerTaxNo())+" eiSellertaxno,"+stringField(getSellerName())+" eiSellername,"+stringField(getTaxNo())+" eiTaxno " +
+                "        ,"+stringField(getBuyerName())+" eiBuyername,"+stringField(getRemark())+" eiRemark,"+stringField(getClerker())+" eiClerker,"+stringField(getPayee())+" eiPayee,"+stringField(getChecker())+" eiChecker" +
+                "        ,"+stringField(getBField1())+" eiBfield1,"+stringField(getBField2())+" eiBfield2,"+stringField(getBField3())+" eiBfield3 " +
+                "    from dual,(select io_id,io_code,io_biid,io_bicode from invoiceorder where io_id = "+ioid+") " +
+                ") b on (nvl(a.ei_orderno,' ') = b.eiorderno) " +
+                "when matched then update set ei_updatedate=sysdate " +
+                "    ,ei_detno = eidetno,ei_sid = eisid,ei_createtime = eicreatetime,ei_invoicetype = eiinvoicetype,ei_invoiceline = eiinvoiceline,ei_specificfactor = eispecificfactor " +
+                "    ,ei_invoicestate = eiinvoicestate,ei_exceptionmessage = eiexceptionmessage,ei_invoicecode = eiinvoicecode,ei_invoicenumber = eiinvoicenumber " +
+                "    ,ei_allelectronicinvoicenumber = eiallelectronicinvoicenumber,ei_oldinvoicecode = eioldinvoicecode,ei_oldinvoicenumber = eioldinvoicenumber,ei_oldallelectronicinvoicenu = eioldallelectronicinvoicenu " +
+                "    ,ei_invoicetime = eiinvoicetime,ei_invalidtime = eiinvalidtime,ei_rushredstate = eirushredstate " +
+                "    ,ei_pdfurl = eipdfurl,ei_ofdurl = eiofdurl,ei_imageurl = eiimageurl,ei_calcexcludingtaxamount = eicalcexcludingtaxamount,ei_calctaxamount = eicalctaxamount,ei_caleorderamount = eicaleorderamount " +
+                "    ,ei_sellertaxno = eisellertaxno,ei_sellername = eisellername,ei_taxno = eitaxno " +
+                "    ,ei_buyername = eibuyername,ei_remark = eiremark,ei_clerker = eiclerker,ei_payee = eipayee,ei_checker = eichecker,ei_bfield1 = eibfield1,ei_bfield2 = eibfield2,ei_bfield3 = eibfield3 " +
+                "when NOT MATCHED THEN insert (ei_id,ei_indate,ei_detno,ei_ioid,ei_iocode,ei_biid,ei_bicode " +
+                "    ,ei_sid,ei_orderno,ei_createtime,ei_invoicetype,ei_invoiceline,ei_specificfactor,ei_invoicestate,ei_exceptionmessage,ei_invoicecode,ei_invoicenumber " +
+                "    ,ei_allelectronicinvoicenumber,ei_oldinvoicecode,ei_oldinvoicenumber,ei_oldallelectronicinvoicenu,ei_invoicetime,ei_invalidtime,ei_rushredstate,ei_pdfurl,ei_ofdurl " +
+                "    ,ei_imageurl,ei_calcexcludingtaxamount,ei_calctaxamount,ei_caleorderamount,ei_sellertaxno,ei_sellername,ei_taxno,ei_buyername,ei_remark,ei_clerker " +
+                "    ,ei_payee,ei_checker,ei_bfield1,ei_bfield2,ei_bfield3) " +
+                "values(elecinvoice_seq.nextval,sysdate,eidetno,io_id,io_code,io_biid,io_bicode " +
+                "    ,eisid,eiorderno,eicreatetime,eiinvoicetype,eiinvoiceline,eispecificfactor,eiinvoicestate,eiexceptionmessage,eiinvoicecode,eiinvoicenumber " +
+                "    ,eiallelectronicinvoicenumber,eioldinvoicecode,eioldinvoicenumber,eioldallelectronicinvoicenu,eiinvoicetime,eiinvalidtime,eirushredstate,eipdfurl,eiofdurl " +
+                "    ,eiimageurl,eicalcexcludingtaxamount,eicalctaxamount,eicaleorderamount,eisellertaxno,eisellername,eitaxno,eibuyername,eiremark,eiclerker " +
+                "    ,eipayee,eichecker,eibfield1,eibfield2,eibfield3)";
+        return sql;
+    }
+    private String numberField(Number v){
+        return (v == null ? "null" : v.toString());
+    }
+    private String stringField(String v){
+        return (v == null ? "null" : "'"+v+"'");
+    }
+    private String timeField(String v){
+        return (v == null ? "null" : "(to_date('1970-01-0100:00:00','yyyy-mm-dd hh24:mi:ss') + "+v+"/1000/24/60/60)");
+    }
+
+}

+ 15 - 0
src/main/java/com/uas/eis/dto/FindOrderRelationInvoiceReq.java

@@ -0,0 +1,15 @@
+package com.uas.eis.dto;
+
+import com.uas.eis.dao.InvoiceGoodsTransportsDTO;
+import com.uas.eis.dao.OrderDTO;
+import com.uas.eis.dao.OrderDetDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FindOrderRelationInvoiceReq {
+    String originalOrderNo;//订单编号
+    String saleTaxNum;//销方税号
+    String needInvoiceSourceDetail;//是否需要发票所来源的订单明细,1-是, 0-否(不填默认 0) 当为0时,将不回传orderDetailCallBackVOS
+}

+ 11 - 0
src/main/java/com/uas/eis/dto/FindOrderRelationInvoiceResp.java

@@ -0,0 +1,11 @@
+package com.uas.eis.dto;
+
+import com.uas.eis.dao.BaseNuoNuoResp;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FindOrderRelationInvoiceResp extends BaseNuoNuoResp {
+    private List<FindOrderRelationInvoiceDTO> data;
+}

+ 24 - 0
src/main/java/com/uas/eis/dto/OrderDetailCallBackVOSDTO.java

@@ -0,0 +1,24 @@
+package com.uas.eis.dto;
+
+import lombok.Data;
+
+@Data
+public class OrderDetailCallBackVOSDTO {
+    private String RowNo;//行编号
+    private String goodsName;//商品名称
+    private String spbm;//商品税收分类编码
+    private String spec;//规格型号
+    private Number num;//本次开票所提交的数量
+    private Number price;//单价,读取含税标志
+    private String unit;//单位
+    private Number taxAmount;//本次开票所提交的金额,读取含税标志
+    private String hsbz;//含税标志 0:不含税 1:含税
+    private String tax;//本次开票所提交的税额
+    private Number zke;//本次开票所提交的折扣额,读取含税标志
+    private Number taxRate;//税率
+    private String dField1;//自定义字段1
+    private String dField2;//自定义字段2
+    private String dField3;//自定义字段3
+    private String dField4;//自定义字段4
+    private String dField5;//自定义字段5
+}

+ 16 - 0
src/main/java/com/uas/eis/dto/RelateRedInvoiceDTO.java

@@ -0,0 +1,16 @@
+package com.uas.eis.dto;
+
+import lombok.Data;
+
+@Data
+public class RelateRedInvoiceDTO {
+    private String orderNo;//红票开票单号
+    private String sid;//红票流水号
+    private String invoiceCode;//红票发票代码
+    private String invoiceNumber;//红票发票号码
+    private String allElectronicInvoiceNumber;//allElectronicInvoiceNumber,红票数电票号码
+    private String invoiceTime;//红票开票日期
+    private Number orderAmount;//红票含税金额
+    private Number excludingTaxAmount;//红票不含税金额
+    private Number taxAmount;//红票税额
+}

+ 18 - 0
src/main/java/com/uas/eis/service/CommonService.java

@@ -0,0 +1,18 @@
+package com.uas.eis.service;
+
+
+import java.util.Map;
+
+/**
+ * @author wuyx
+ * @email wuyx@usoftchina.com
+ * @date 2023-07-27
+ */
+public interface CommonService {
+    //记录成功日志
+    void logSRecord(String code_,int keyvalue_);
+    //记录失败日志
+    void logFRecord(String code_,String err_,int keyvalue_);
+
+    int saveFilePath(String path, int size, String fileName, String emName);
+}

+ 2 - 0
src/main/java/com/uas/eis/service/ERPService.java

@@ -15,4 +15,6 @@ public interface ERPService {
     Map<String, Object> invoiceOrderSubmitKp(String master,int id);
     Map<String, Object> findOrderState(String master,int id);
     Map<String, Object> cancelInvoiceOrder(String master, int id);
+    Map<String, Object> getElecInvoicesById(String master, Integer id);
+    Map<String, Object> getElecInvoices(String appKey,String appSecret,String token,String taxnum,int ioid,String ioCode);
 }

+ 41 - 0
src/main/java/com/uas/eis/service/Impl/CommonServiceImpl.java

@@ -0,0 +1,41 @@
+package com.uas.eis.service.Impl;
+
+import com.uas.eis.dao.*;
+import com.uas.eis.entity.Employee;
+import com.uas.eis.service.CommonService;
+import com.uas.eis.utils.Constant;
+import com.uas.eis.utils.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+@Service
+public class CommonServiceImpl implements CommonService {
+    @Autowired
+    private BaseDao baseDao;
+
+    @Override
+    public void logSRecord(String code_, int keyvalue_) {
+        baseDao.execute("insert into invoicedockLog(id_,code_,date_,result_,keyvalue_) values (invoicedockLog_seq.nextval,?,sysdate,'SUCCEED',?)",code_,keyvalue_);
+    }
+
+    @Override
+    public void logFRecord(String code_, String err_, int keyvalue_) {
+        baseDao.execute("insert into invoicedockLog(id_,code_,date_,result_,err_,keyvalue_) values (invoicedockLog_seq.nextval,?,sysdate,'FAILED',?,?)",code_,err_,keyvalue_);
+    }
+    @Override
+    public int saveFilePath(String path, int size, String fileName, String emName) {
+        int id = baseDao.getSeqId("EMAILFILEPATH");
+        if (path.contains("\\")) {//上传到本地返回路径修改
+            path = path.replace("\\", "/");
+        }
+        /**
+         * 文件名含单引号无法下载*/
+        fileName=fileName.replaceAll(",", ",");
+        baseDao.execute("INSERT INTO filepath(fp_id,fp_path,fp_size,fp_man,fp_date,fp_name) values(" + id + ",'" + path + "'," + size
+                + ",'"+emName+"'," + DateUtil.parseDateToOracleString(Constant.YMD_HMS, new Date()) + ",'" + fileName
+                + "')");
+        return id;
+    }
+}

+ 119 - 7
src/main/java/com/uas/eis/service/Impl/ERPServiceImpl.java

@@ -10,9 +10,13 @@ import com.uas.eis.config.DonlimConfig;
 import com.uas.eis.core.config.SpObserver;
 import com.uas.eis.core.support.TokenProperties;
 import com.uas.eis.dao.*;
+import com.uas.eis.dto.FindOrderRelationInvoiceDTO;
+import com.uas.eis.dto.FindOrderRelationInvoiceReq;
+import com.uas.eis.dto.FindOrderRelationInvoiceResp;
 import com.uas.eis.entity.*;
 import com.uas.eis.sdk.entity.ApiResult;
 import com.uas.eis.sdk.resp.ApiResponse;
+import com.uas.eis.service.CommonService;
 import com.uas.eis.service.ERPService;
 import com.uas.eis.utils.*;
 import nuonuo.open.sdk.NNOpenSDK;
@@ -40,6 +44,8 @@ public class ERPServiceImpl implements ERPService {
 
     @Autowired
     private DonlimConfig donlimConfig;
+    @Autowired
+    private CommonService commonService;
     @Override
     public Map<String, Object> pushInvoiceOrder(String master, int id) {
         Map<String, Object> map = new HashMap<String, Object>();
@@ -172,24 +178,24 @@ public class ERPServiceImpl implements ERPService {
             return null;//对接信息为配置
         }
         String url=donlimConfig.getRoute();
-        System.out.println(url);
+//        System.out.println(url);
         String appKey = donlimConfig.getAppKey();
         String appSecret = donlimConfig.getAppSecret();
         String token =  donlimConfig.getToken();
         String taxnum=  donlimConfig.getTaxnum();
         if(donlimConfig.isProd()){
-            System.out.println("prod");
+//            System.out.println("prod");
             appKey =  obs[0].toString();
             appSecret =  obs[1].toString();
             token = obs[2].toString();// 访问令牌
             taxnum = obs[3].toString();// 授权企业税号
         }else{
-            System.out.println("dev");
+//            System.out.println("dev");
         }
         SpObserver.putSp(master);
         SqlRowList rs_main = baseDao.queryForRowSet("select * from invoiceOrder left join customer on io_cucode=cu_code where io_id="+id);
         if(rs_main.next()){
-            System.out.println(taxnum);
+//            System.out.println(taxnum);
             String code= rs_main.getGeneralString("io_code");
             NNOpenSDK sdk = NNOpenSDK.getIntance();
             String method = "nuonuo.OpeMplatform.findOrderState"; // API方法名
@@ -199,12 +205,18 @@ public class ERPServiceImpl implements ERPService {
             String content=JSONArray.toJSONString(reqParam);
             String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识,32位随机码,无需修改,保持默认即可
             String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
+            System.out.println(result);
             FindOrderStateResp resp = JSON.parseObject(result , new TypeReference<FindOrderStateResp>() {});
             System.out.println(resp.getCode());
             System.out.println(resp.getMessage());
-            System.out.println(resp.getData().getInvoiceStatus());
-            System.out.println(resp.getData().getErrorMsg());
-            System.out.println(result);//{"status":"0000","message":"调用成功","data":{"invoiceStatus":"0","errorMsg":null}}
+//            System.out.println(resp.getData().getInvoiceStatus());
+//            System.out.println(resp.getData().getErrorMsg());
+//            Map<Object, Object> res=JSONUtil.toMap(result);
+            baseDao.execute("update invoiceOrder set IO_INVOICESTATUS = '"+resp.getData().getInvoiceStatus()+"'"
+                        +",io_errorMsg='"+StringUtil.nvl(resp.getData().getErrorMsg(),"")+"'"
+//                    +(StringUtil.hasText(resp.getData().getErrorMsg())?",io_errorMsg ='"+resp.getData().getErrorMsg()+"'":"")
+                    +" where io_id = '"+id+"'");
+//            System.out.println(result);//{"status":"0000","message":"调用成功","data":{"invoiceStatus":"0","errorMsg":null}}
             map.put("success", true);
             map.put("result", result);
             return map;
@@ -271,4 +283,104 @@ public class ERPServiceImpl implements ERPService {
         }
         return null;
     }
+
+    @Override
+    public Map<String, Object> getElecInvoicesById(String master, Integer id) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        Object[] obs=baseDao.getFieldsDataByCondition("YITOA_DATACENTER.dock_invoice_config",new String[]{"appKey","appSecret","token","taxnum"},"username='"+master+"'");
+        if(obs==null){
+            return null;//对接信息为配置
+        }
+//        System.out.println(url);
+        String appKey = donlimConfig.getAppKey();
+        String appSecret = donlimConfig.getAppSecret();
+        String token =  donlimConfig.getToken();
+        String taxnum=  donlimConfig.getTaxnum();
+        if(donlimConfig.isProd()){
+//            System.out.println("prod");
+            appKey =  obs[0].toString();
+            appSecret =  obs[1].toString();
+            token = obs[2].toString();// 访问令牌
+            taxnum = obs[3].toString();// 授权企业税号
+        }else{
+//            System.out.println("dev");
+        }
+        SpObserver.putSp(master);
+        SqlRowList ioList = baseDao.queryForRowSet("select io_id,io_code from "+master+".invoiceOrder left join "+master+".customer on io_cucode=cu_code " +
+                " where io_id = "+id);
+        while(ioList.next()) {
+            map = getElecInvoices(appKey,appSecret,token,taxnum,ioList.getGeneralInt("io_id"),ioList.getGeneralString("io_code"));
+        }
+        return map;
+    }
+    @Override
+    public Map<String, Object> getElecInvoices(String appKey,String appSecret,String token,String taxnum,int ioid,String ioCode){
+        Map<String, Object> res = new HashMap<String, Object>();
+        String url=donlimConfig.getRoute();
+        String errCode = "-999";
+        String errMsg = "";
+        try {
+            //调用对接
+            FindOrderRelationInvoiceReq foriReq = new FindOrderRelationInvoiceReq();
+            foriReq.setOriginalOrderNo(ioCode);//订单编号
+            foriReq.setSaleTaxNum(taxnum);//销方税号
+            foriReq.setNeedInvoiceSourceDetail("0");//是否需要发票所来源的订单明细,1-是, 0-否(不填默认 0) 当为0时,将不回传orderDetailCallBackVOS。先默认不需要明细
+    //                    System.out.println(JSONArray.toJSONString(foriReq));
+            NNOpenSDK sdk = NNOpenSDK.getIntance();
+            String method = "nuonuo.OpeMplatform.findOrderRelationInvoice"; // API方法名
+            String content =sdk.convertToUtf8(JSONArray.toJSONString(foriReq));
+            String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识,32位随机码,无需修改,保持默认即可
+            String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
+    //                    System.out.println(result);
+            FindOrderRelationInvoiceResp resp = JSON.parseObject(result , new TypeReference<FindOrderRelationInvoiceResp>() {});
+            errCode = resp.getStatus();
+            errMsg = resp.getMessage();
+            logger.info("ElecInvoice-DownLoad-master: {} ,id {} status {} message {}",SpObserver.getSp(),ioid,errCode,errMsg);
+            if("0000".equals(errCode)){//调用成功
+                //记录发票明细
+                baseDao.execute(getElecInvoicesSqls(ioid,resp.getData()));
+                commonService.logSRecord("订单关联发票对接",ioid);
+            }else if(!"8958".equals(errCode)){//  {"status":"8958","message":"该订单对应的开票单不存在","data":null} 没有开票单的不记录对接失败日志
+                if(errMsg.length() > 3990){
+                    errMsg = errMsg.substring(0,3990);
+                }
+                baseDao.execute("update invoiceOrder set io_errorMsg='"+errMsg+"' where io_id="+ioid);
+                commonService.logFRecord("订单关联发票对接","("+errCode+")"+errMsg,ioid);
+            }
+        }catch (Exception e){
+            errMsg = "发票获取异常";
+            if(StringUtil.hasText(e.getMessage())){
+                errMsg = e.getMessage();
+            }else if(e.getCause()!=null&&StringUtil.hasText(e.getCause().getMessage())){
+                errMsg = e.getCause().getMessage();
+            }
+            commonService.logFRecord("订单关联发票对接",errMsg.replaceAll("'","''"),ioid);
+        }
+        if(StringUtil.hasText(errMsg)&&!"调用成功".equals(errMsg)){
+            res.put("success", false);
+            res.put("errCode", errCode);
+            res.put("errMsg", errMsg);
+        }else {
+            res.put("success", true);
+        }
+        return res;
+    }
+    private List<String> getElecInvoicesSqls(int ioid,List<FindOrderRelationInvoiceDTO> data){
+        List<String> sqls = new ArrayList<String>();
+        boolean syncToBillOut = baseDao.isDBSetting("BillOut","syncToBillOut");
+        for (int i = 0; i < data.size(); i++) {
+            sqls.add(data.get(i).toMergeSql(ioid,(i+1)));
+        }
+        sqls.add("update ELECINVOICE set ei_refno = (case when ei_invoiceLine in ('bs','pc','es','ec') then ei_allElectronicInvoiceNumber else ei_invoiceNumber end) " +
+                "where ei_ioid = "+ioid+" and EI_INVOICESTATE = 1 and EI_EXCEPTIONMESSAGE is null and (ei_allElectronicInvoiceNumber is not null or ei_invoiceNumber is not null )");
+        sqls.add("update invoiceOrder set io_refno = (select (min(ei_refno)||(case when max(ei_refno) <> min(ei_refno) then '-'||max(ei_refno) else '' end)) from ELECINVOICE where ei_ioid = io_id)" +
+                "where io_id = "+ioid);
+        //更新开票记录
+        if(syncToBillOut){
+            sqls.add("update BillOut set bi_refno = (select max(io_refno) from invoiceOrder where io_id = "+ioid+" and io_biid = bi_id) where bi_id in (select io_biid from invoiceOrder where io_id = "+ioid+" and io_refno is not null)");
+        }
+        //System.out.println("sqls:");
+//        System.out.println(sqls);
+        return sqls;
+    }
 }

+ 176 - 0
src/main/java/com/uas/eis/task/ElecInvoiceTask.java

@@ -0,0 +1,176 @@
+package com.uas.eis.task;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.uas.eis.config.DonlimConfig;
+import com.uas.eis.config.PNSConfig;
+import com.uas.eis.core.config.SpObserver;
+import com.uas.eis.core.support.TokenProperties;
+import com.uas.eis.dao.BaseDao;
+import com.uas.eis.dao.FindOrderStateResp;
+import com.uas.eis.dao.SqlRowList;
+import com.uas.eis.dto.FindOrderRelationInvoiceDTO;
+import com.uas.eis.dto.FindOrderRelationInvoiceReq;
+import com.uas.eis.dto.FindOrderRelationInvoiceResp;
+import com.uas.eis.entity.PNSSendData;
+import com.uas.eis.entity.PNSSendResp;
+import com.uas.eis.service.CommonService;
+import com.uas.eis.service.ERPService;
+import com.uas.eis.utils.*;
+import net.sf.json.JSONObject;
+import nuonuo.open.sdk.NNOpenSDK;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.http.HttpStatus;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.*;
+
+@Component
+public class ElecInvoiceTask {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    @Autowired
+    private BaseDao baseDao;
+    @Autowired
+    private DonlimConfig donlimConfig;
+    @Autowired
+    private ERPService erpService;
+    @Autowired
+    private CommonService commonService;
+    /**
+     * 每半小时执行一次
+     *  //0:待处理 表示订单没有转了开票申请,此状态可以不用管
+     * //1:处理中 表示订单可能转了开票申请,但是在走审批流等,此状态可以先不用管
+     * //2:已处理 表示订单全部都转了开票申请
+     * //4:提交失败 表示订单自动转失败了,此状态可以不用管
+     * /*6:部分待处理 表示订单部分转了开票申请
+     *     1.有开票记录申请,但是没开票
+     *          {"status":"8958","message":"该订单对应的开票单不存在","data":null}
+     *     2.有开票记录申请,存在部分失败或者成功
+     *          只返回开票失败或者成功的部分
+     *          {"status":"0000","message":"调用成功","data":[{"sellerTaxNo":"339901999999199","orderNo":"1134068619401396224","rushRedState":"0","invoiceType":1,"invoiceState":1,"invoiceLine":"b","exceptionMessage":"ukey版签章无下载码","sid":"23072713481601034933"}]}
+     * //7:无需开票,此状态可以不用管
+     * */
+    @Scheduled(cron = "0 0/30 * * * ?")
+    public void elecInvoiceDownLoad(){
+        List<Object[]> obsList=baseDao.getFieldsDatasByCondition("YITOA_DATACENTER.dock_invoice_config",new String[]{"appKey","appSecret","token","taxnum","username"},"1=1");
+        if(!CollectionUtil.isEmpty(obsList)){
+            logger.info("ElecInvoice-DownLoad Begin");
+            for (Object[] obs: obsList) {
+                if(obs == null){
+                    continue;
+                }
+                String master = obs[4].toString();
+                String appKey = donlimConfig.getAppKey();
+                String appSecret = donlimConfig.getAppSecret();
+                String token =  donlimConfig.getToken();
+                String taxnum=  donlimConfig.getTaxnum();
+                if(donlimConfig.isProd()){
+                    System.out.println("prod");
+                    appKey =  obs[0].toString();
+                    appSecret =  obs[1].toString();
+                    token = obs[2].toString();// 访问令牌
+                    taxnum = obs[3].toString();// 授权企业税号
+                }else{
+                    System.out.println("dev");
+                }
+                logger.info("ElecInvoice-DownLoad: master: {} Begin ",master);
+                SpObserver.putSp(master);
+                SqlRowList ioList = baseDao.queryForRowSet("select io_id,io_code from "+master+".invoiceOrder left join "+master+".customer on io_cucode=cu_code " +
+                        " where io_status = '已审核' and nvl(IO_DOCKSTATUS,' ') = '对接成功' and (IO_INVOICESTATUS = 6 or (IO_INVOICESTATUS = 2 and io_refno is null))");
+                logger.info("ElecInvoice-DownLoad: master: {} size: {} ",master,ioList.getResultList().size());
+                while (ioList.next()){
+                    erpService.getElecInvoices(appKey,appSecret,token,taxnum,ioList.getGeneralInt("io_id"),ioList.getGeneralString("io_code"));
+                }
+                logger.info("ElecInvoice-DownLoad: master: {} End ",master);
+            }
+            logger.info("ElecInvoice-DownLoad End");
+        }
+    }
+    @Scheduled(cron = "0 0/5 * * * ?")
+    //PDF文件转存 一次转存
+    public void elecInvoiceAttachSave(){
+        long t1 = System.currentTimeMillis();
+        List<Object[]> obsList=baseDao.getFieldsDatasByCondition("YITOA_DATACENTER.dock_invoice_config",new String[]{"appKey","appSecret","token","taxnum","username"},"1=1");
+        if(!CollectionUtil.isEmpty(obsList)){
+            logger.info("ElecInvoice-AttachSave Begin");
+            for (Object[] obs: obsList) {
+                if(obs == null){
+                    continue;
+                }
+                String master = obs[4].toString();
+                logger.info("ElecInvoice-AttachSave: master: {} Begin ",master);
+                SpObserver.putSp(master);
+                SqlRowList ioList = baseDao.queryForRowSet("select * from (select ei_id,ei_pdfurl,ei_refno,ei_ioid from ELECINVOICE " +
+                        "where ei_pdfurl is not null and ei_pdfattach is null " +
+//                        "and ei_id = 11" +
+                        " order by ei_id ) where rownum <= 100 ");//一次最多500
+                logger.info("ElecInvoice-AttachSave: master: {} size: {} ",master,ioList.getResultList().size());
+                List<Integer> ioids = new ArrayList<>();
+                while (ioList.next()){
+                    long tt1 = System.currentTimeMillis();
+                    //下载地址
+                    String fileUrl = ioList.getGeneralString("ei_pdfurl"); // "https://inv.jss.com.cn/fp2/2zpnwyKkdvu9dWzE8BhmSnER0Iux3xQRMLidDJhiIE2PziVXY4lL3k83OsK0K06YctW5cf1FFHxraffj-bf16A.pdf";
+                    // 定义要保存的文件的路径
+                    String fileName = ioList.getGeneralString("ei_refno")+".pdf";//发票号码
+                    String fileBasePath = "C:\\invoice\\"+fileName;//发票号码
+                    if(donlimConfig.isProd()){
+                        fileBasePath = "\\usr\\local\\uas\\invoice\\"+fileName;//发票号码
+                    }
+                    try {
+                        // 创建URL对象
+                        URL url = new URL(fileUrl);
+                        // 打开连接
+                        URLConnection conn = url.openConnection();
+                        // 获取输入流
+                        InputStream in = conn.getInputStream();
+                        // 创建输出流
+                        FileOutputStream out = new FileOutputStream(fileBasePath);
+                        // 创建缓冲区
+                        byte[] buffer = new byte[104857600];
+                        // 读取并写入数据
+                        int len;
+                        while ((len = in.read(buffer)) != -1) {
+                            out.write(buffer, 0, len);
+                        }
+                        long size = out.getChannel().size();
+                        // 关闭流
+                        in.close();
+                        out.close();
+//                        System.out.println("size:"+size);
+                        //存文件 filepath
+                        int id = commonService.saveFilePath(fileBasePath, (int) size, fileName, "管理员");
+                        baseDao.execute("update ELECINVOICE set ei_pdfattach ='"+id+";' where ei_id = "+ioList.getGeneralInt("ei_id"));
+                        if(!ioids.contains(ioList.getGeneralInt("ei_ioid"))){
+                            ioids.add(ioList.getGeneralInt("ei_ioid"));
+                        }
+                        System.out.println("下载成功");
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    long tt2 = System.currentTimeMillis();
+                    System.out.println("tt1->tt2: "+(tt2 - tt1));
+                }
+                if(ioids.size()>0){
+                    baseDao.execute("update invoiceOrder set io_attach = REPLACE(to_char((select wm_concat(ei_pdfattach) from ELECINVOICE where io_id = ei_ioid)),',','') where io_id in ("+StringUtils.join(ioids.toArray(), ",")+")");
+                }
+                logger.info("ElecInvoice-AttachSave: master: {} End ",master);
+            }
+            logger.info("ElecInvoice-AttachSave End");
+        }
+        long t2 = System.currentTimeMillis();
+        System.out.println("t1->t2: "+(t2-t1));
+    }
+}

+ 55 - 0
src/main/java/com/uas/eis/task/InvoiceOrderTask.java

@@ -0,0 +1,55 @@
+package com.uas.eis.task;
+
+import com.uas.eis.dao.BaseDao;
+import com.uas.eis.dao.SqlRowList;
+import com.uas.eis.service.ERPService;
+import com.uas.eis.utils.CollectionUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class InvoiceOrderTask {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    @Autowired
+    private BaseDao baseDao;
+    @Autowired
+    private ERPService erpService;
+    /**
+     * 每10分钟执行
+     *  	//订单状态(0:待处理 1:处理中 2:已处理 4:提交失败 6:部分待处理 7:无需开票)
+     * 		//0:待处理 表示订单没有转了开票申请,此状态需要定时获取
+     * 		//1:处理中 表示订单可能转了开票申请,此状态需要定时获取
+     * 		//2:已处理 表示订单全部都转了开票申请,没有发票号的情况下要继续获取订单状态。
+     * 		//4:提交失败 表示订单自动转失败了,此状态需要定时获取
+     *      //6:部分待处理 表示订单部分转了开票申请,此状态需要定时获取
+     * 		//7:无需开票,此状态可以不用管,此状态需要定时获取
+     * */
+    @Scheduled(cron = "0 0/10 * * * ?")
+    public void InvoiceOrderStateUpdate(){
+        List<Object[]> obsList=baseDao.getFieldsDatasByCondition("YITOA_DATACENTER.dock_invoice_config",new String[]{"appKey","appSecret","token","taxnum","username"},"1=1");
+        if(!CollectionUtil.isEmpty(obsList)){
+            logger.info("InvoiceOrder-StateUpdate Begin");
+            for (Object[] obs: obsList) {
+                if(obs == null){
+                    continue;
+                }
+                String master = obs[4].toString();
+                logger.info("ElecInvoice-DownLoad: master: {} Begin ",master);
+                SqlRowList ioList = baseDao.queryForRowSet("select io_id,io_code from "+master+".invoiceOrder left join "+master+".customer on io_cucode=cu_code " +
+                        " where IO_STATUS ='已审核' and IO_DOCKSTATUS = '对接成功' and (nvl(IO_INVOICESTATUS,0) in (0,1,4,6,7) or (IO_INVOICESTATUS = 2 and io_refno is null)) order by io_id");
+                logger.info("InvoiceOrder-StateUpdate: master: {} size: {} ",master,ioList.getResultList().size());
+                while (ioList.next()){
+                    Map<String, Object> mm = erpService.findOrderState(master, ioList.getGeneralInt("io_id"));
+                }
+                logger.info("InvoiceOrder-StateUpdate: master: {} End ",master);
+            }
+            logger.info("InvoiceOrder-StateUpdate End");
+        }
+    }
+}

+ 84 - 27
src/test/java/com/uas/eis/UasEisApplicationTests.java

@@ -1,15 +1,13 @@
 package com.uas.eis;
 
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.TypeReference;
 import com.uas.eis.config.DonlimConfig;
-import com.uas.eis.core.config.SpObserver;
 import com.uas.eis.dao.*;
 import com.uas.eis.service.ERPService;
-import com.uas.eis.utils.JSONUtil;
+import com.uas.eis.task.ElecInvoiceTask;
+import com.uas.eis.task.InvoiceOrderTask;
 import nuonuo.open.sdk.NNOpenSDK;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -17,6 +15,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
@@ -29,7 +30,10 @@ public class UasEisApplicationTests {
 	private ERPService erpService;
 	@Autowired
 	private DonlimConfig donlimConfig;
-
+	@Autowired
+	private ElecInvoiceTask elecInvoiceTask;
+	@Autowired
+	InvoiceOrderTask invoiceOrderTask;
 	/**
 	 * 	开票订单对接
 	 */
@@ -96,23 +100,25 @@ public class UasEisApplicationTests {
 	 */
 	@Test
 	public void TestfindOrderState() {
-		NNOpenSDK sdk = NNOpenSDK.getIntance();
-		String taxnum ="339901999999199";////测试
-		String appKey = "78607195";
-		String appSecret = "26A860C451744A21";
-		String method = "nuonuo.OpeMplatform.findOrderState"; // API方法名
-		String url = "https://sdk.nuonuo.com/open/v1/services";//SDK请求地址
-		String token = "77f21f617f87135fcd97ef1ueud3dxdi";
-		Map<String,Object> reqParam=new HashMap<>();
-		reqParam.put("originalOrderNo","SZ23070013");
-		reqParam.put("saleTaxNum","339901999999199");
-		String content=JSONArray.toJSONString(reqParam);
-//                content=sdk.convertToUtf8(content);
-		System.out.println(content);
-//                content = "{\"originalOrderNo\": \"SZ23070004\", \"saleTaxNum\":[\"339901999999199\"], \"needInvoiceSourceDetail\":\"1\" }";
-		String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识,32位随机码,无需修改,保持默认即可
-		String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
-		System.out.println(result);
+		String OrderCode = "SZ23070005";
+		SqlRowList io = baseDao.queryForRowSet("SELECT io_id FROM N_HUASL_SZ.invoiceOrder where IO_STATUS ='已审核' and IO_DOCKSTATUS = '对接成功' " +
+//				"and nvl(IO_INVOICESTATUS,0) in(0,1,6) " +
+				"and io_code = '"+OrderCode+"'" +
+				"order by io_id ");
+		//订单状态(0:待处理 1:处理中 2:已处理 4:提交失败 6:部分待处理 7:无需开票)
+		//0:待处理 表示订单没有转了开票申请,此状态需要定时获取
+		//1:处理中 表示订单可能转了开票申请,此状态需要定时获取
+		//2:已处理 表示订单全部都转了开票申请,没有发票号的情况下要继续获取订单状态。
+		//4:提交失败 表示订单自动转失败了,此状态需要定时获取
+        //6:部分待处理 表示订单部分转了开票申请,此状态需要定时获取
+		//7:无需开票,此状态可以不用管,此状态需要定时获取
+		while (io.next()){
+			Map<String, Object> mm = erpService.findOrderState("N_HUASL_SZ", io.getGeneralInt("io_id"));
+		}
+	}
+	@Test
+	public void TestInvoiceOrderStateUpdate(){
+		invoiceOrderTask.InvoiceOrderStateUpdate();
 	}
 	/**
 	 *  查询订单关联发票接口 nuonuo.OpeMplatform.findOrderRelationInvoice
@@ -127,15 +133,66 @@ public class UasEisApplicationTests {
 		String url = "https://sdk.nuonuo.com/open/v1/services";//SDK请求地址
 		String token = "77f21f617f87135fcd97ef1ueud3dxdi";
 		Map<String,Object> reqParam=new HashMap<>();
-		reqParam.put("needInvoiceSourceDetail","1");// 是否需要发票所来源的订单明细,1-是, 0-否(不填默认 0) 当为0时,将不回传orderDetailCallBackVOS
-		reqParam.put("originalOrderNo","SZ23070016");
+		reqParam.put("needInvoiceSourceDetail","0");// 是否需要发票所来源的订单明细,1-是, 0-否(不填默认 0) 当为0时,将不回传orderDetailCallBackVOS
+		//SZ23070026
+		//betaRTC-202105-003180-209
+		reqParam.put("originalOrderNo","SZ23070018");//部分待处理-没开票 {"status":"8958","message":"该订单对应的开票单不存在","data":null}
 		reqParam.put("saleTaxNum","339901999999199");
+		// invoiceState = 1 开票状态,合并冲销时为空 1:开票成功 2:开票失败
+		//exceptionMessage 开票异常信息,开票失败状态时返回
 		String content=JSONArray.toJSONString(reqParam);
-//                content=sdk.convertToUtf8(content);
-		System.out.println(content);
-//                content = "{\"originalOrderNo\": \"SZ23070004\", \"saleTaxNum\":[\"339901999999199\"], \"needInvoiceSourceDetail\":\"1\" }";
+//     content=sdk.convertToUtf8(content);
+//		System.out.println(content);
 		String senid = UUID.randomUUID().toString().replace("-", ""); // 唯一标识,32位随机码,无需修改,保持默认即可
 		String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, token, taxnum, method, content);
 		System.out.println(result);
 	}
+
+	@Test
+	public void TestDownLoadElecInvoice(){
+		Map<String, Object> m = erpService.getElecInvoicesById("N_HUASL_SZ", 25);
+		System.out.println(JSONObject.toJSONString(m));
+//		elecInvoiceTask.elecInvoiceDownLoad();
+	}
+
+	//文件转存
+	//https://inv.jss.com.cn/fp2/2zpnwyKkdvu9dWzE8BhmSnER0Iux3xQRMLidDJhiIE2PziVXY4lL3k83OsK0K06YctW5cf1FFHxraffj-bf16A.pdf
+	@Test
+	public void TestPdfDowLoad(){
+		//下载地址
+		String fileUrl = "https://inv.jss.com.cn/fp2/2zpnwyKkdvu9dWzE8BhmSnER0Iux3xQRMLidDJhiIE2PziVXY4lL3k83OsK0K06YctW5cf1FFHxraffj-bf16A.pdf";
+		// 定义要保存的文件的路径
+		String filePath = "C:\\invoice\\988038486766_00007404.pdf";//开票代码_发票号码
+		try {
+			// 创建URL对象
+			URL url = new URL(fileUrl);
+			// 打开连接
+			URLConnection conn = url.openConnection();
+			// 获取输入流
+			InputStream in = conn.getInputStream();
+			// 创建输出流
+			OutputStream out = new FileOutputStream(filePath);
+			// 创建缓冲区
+			byte[] buffer = new byte[1024];
+			// 读取并写入数据
+			int len;
+			while ((len = in.read(buffer)) != -1) {
+				out.write(buffer, 0, len);
+			}
+			// 关闭流
+			in.close();
+			out.close();
+			//存文件 filepath
+			System.out.println("下载成功");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Test
+	public void TestElecInvoiceAttachSave(){
+		elecInvoiceTask.elecInvoiceAttachSave();
+	}
+
+
 }