Просмотр исходного кода

OMS发票信息部分代码上传

徐滕 1 месяц назад
Родитель
Сommit
0fc630d2f5
20 измененных файлов с 440 добавлено и 130 удалено
  1. 31 3
      src/main/java/com/jeeplus/common/config/Global.java
  2. 3 3
      src/main/java/com/jeeplus/modules/ruralprojectrecords/web/RuralProjectSignatureOldMessageDisposeController.java
  3. 1 1
      src/main/java/com/jeeplus/modules/workcalendar/service/WorkCalendarTaskService.java
  4. 8 0
      src/main/java/com/jeeplus/modules/workinvoice/dao/WorkInvoiceDao.java
  5. 9 0
      src/main/java/com/jeeplus/modules/workinvoice/entity/WorkInvoice.java
  6. 84 0
      src/main/java/com/jeeplus/modules/workinvoice/entity/WorkInvoiceTaxClassificationCode.java
  7. 4 3
      src/main/java/com/jeeplus/modules/workinvoice/service/OMS/InvoiceDownloadService.java
  8. 76 39
      src/main/java/com/jeeplus/modules/workinvoice/service/OMS/OMSDisposeService.java
  9. 3 3
      src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceDownloadService.java
  10. 3 3
      src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceScheduledService.java
  11. 33 1
      src/main/java/com/jeeplus/modules/workinvoice/service/WorkInvoiceService.java
  12. 73 0
      src/main/java/com/jeeplus/modules/workinvoice/thread/ApprovalThread.java
  13. 53 0
      src/main/java/com/jeeplus/modules/workinvoice/thread/RedApprovalThread.java
  14. 39 22
      src/main/java/com/jeeplus/modules/workinvoice/utils/OMSNationUtil.java
  15. 3 3
      src/main/java/com/jeeplus/modules/workinvoice/utils/RedInvoiceScheduledTask.java
  16. 2 2
      src/main/resources/jeeplus.properties
  17. 8 2
      src/main/resources/mappings/modules/workinvoice/WorkInvoiceDao.xml
  18. 1 0
      src/main/webapp/static/common/jeeplus.js
  19. 6 6
      src/main/webapp/webpage/modules/workinvoice/workInvoiceAuditEnd.jsp
  20. 0 39
      src/main/webapp/webpage/modules/workinvoice/workInvoiceTwoForm.jsp

+ 31 - 3
src/main/java/com/jeeplus/common/config/Global.java

@@ -7,6 +7,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.Reader;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.Map;
 import java.util.Properties;
@@ -78,9 +79,36 @@ public class Global {
 	 */
 	public static String getConfig(String key) {
 		String value = map.get(key);
-		if (value == null){
-			value = loader.getProperty(key);
-			map.put(key, value != null ? value : StringUtils.EMPTY);
+		if (value == null) {
+			String rawValue = loader.getProperty(key);
+			// 空值直接赋值为空字符串
+			if (rawValue == null) {
+				value = StringUtils.EMPTY;
+			} else {
+				// 直接在方法内判断是否为ASCII字符(无额外方法)
+				boolean isAscii = true;
+				for (char c : rawValue.toCharArray()) {
+					if (c > 127) { // 非ASCII字符(中文乱码)
+						isAscii = false;
+						break;
+					}
+				}
+
+				if (isAscii) {
+					// ASCII字符(英文/数字)直接用原始值
+					value = rawValue;
+				} else {
+					// 非ASCII字符,执行中文乱码转码,加容错
+					try {
+						value = new String(rawValue.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
+					} catch (Exception e) {
+						// 转码失败降级用原始值,不报错
+						value = rawValue;
+					}
+				}
+			}
+			// 缓存处理后的结果
+			map.put(key, value);
 		}
 		return value;
 	}

+ 3 - 3
src/main/java/com/jeeplus/modules/ruralprojectrecords/web/RuralProjectSignatureOldMessageDisposeController.java

@@ -952,9 +952,9 @@ public class RuralProjectSignatureOldMessageDisposeController extends BaseContro
      * 给accessToken查询的有效时间设置为1天
      */
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
 
     /**
      * 开具蓝票

+ 1 - 1
src/main/java/com/jeeplus/modules/workcalendar/service/WorkCalendarTaskService.java

@@ -525,7 +525,7 @@ public class WorkCalendarTaskService  {
      * 用于发票开票时报9998错误时进行重新处理的方法
      * 和开票系统相关的定时任务
      */
-    //@Scheduled(cron = "0 */2 * * * ?")
+    @Scheduled(cron = "0 */10 * * * ?")
     @Transactional(readOnly = false)
     public void redInvoiceRetryScheduledTask() {
         redInvoiceRetryScheduledService.handleInvoice9998RetryTask();

+ 8 - 0
src/main/java/com/jeeplus/modules/workinvoice/dao/WorkInvoiceDao.java

@@ -11,6 +11,7 @@ import com.jeeplus.common.persistence.CrudDao;
 import com.jeeplus.common.persistence.annotation.MyBatisDao;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoiceProjectRelation;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceTaxClassificationCode;
 import org.apache.ibatis.annotations.Param;
 import org.apache.poi.ss.formula.functions.T;
 
@@ -265,4 +266,11 @@ public interface WorkInvoiceDao extends CrudDao<WorkInvoice> {
 	 * @return
 	 */
 	Integer updateConfirmationSlipResultStr(WorkInvoice workInvoice);
+
+	/**
+	 * 查询税收分类对应信息
+	 * @param workInvoice
+	 * @return
+	 */
+	WorkInvoiceTaxClassificationCode getBillingContentDetail(WorkInvoice workInvoice);
 }

+ 9 - 0
src/main/java/com/jeeplus/modules/workinvoice/entity/WorkInvoice.java

@@ -138,6 +138,7 @@ public class WorkInvoice extends ActEntity<WorkInvoice> {
 	private List<WorkInvoiceCloud> workInvoiceCloudList;
 	private String isSzCloud; //判断是否是苏州分公司的发票数据
 
+	private String goodsTaxno;		// 税收分类编码
 
 
 	private String omsAccessTokenError; //开具发票时,获取token失败报错信息保存
@@ -1073,4 +1074,12 @@ public class WorkInvoice extends ActEntity<WorkInvoice> {
 	public void setConfirmationSlipResultStr(String confirmationSlipResultStr) {
 		this.confirmationSlipResultStr = confirmationSlipResultStr;
 	}
+
+	public String getGoodsTaxno() {
+		return goodsTaxno;
+	}
+
+	public void setGoodsTaxno(String goodsTaxno) {
+		this.goodsTaxno = goodsTaxno;
+	}
 }

+ 84 - 0
src/main/java/com/jeeplus/modules/workinvoice/entity/WorkInvoiceTaxClassificationCode.java

@@ -0,0 +1,84 @@
+package com.jeeplus.modules.workinvoice.entity;
+
+import com.jeeplus.common.persistence.DataEntity;
+
+public class WorkInvoiceTaxClassificationCode extends DataEntity<WorkInvoiceTaxClassificationCode> {
+
+    /**
+     * 项目名称
+     */
+    private String goodName;
+
+    /**
+     * 税率
+     */
+    private Double taxRate;
+
+    /**
+     * 含税标志(0:不含税;1:含税)
+     */
+    private String priceTax;
+
+    /**
+     * 商品税收分类编码
+     */
+    private String goodsTaxno;
+
+    /**
+     * 商品和服务分类简称
+     */
+    private String goodsTypeAbbreviation;
+
+    /**
+     * 关联id
+     */
+    private String billingContentId;
+
+    public String getGoodName() {
+        return goodName;
+    }
+
+    public void setGoodName(String goodName) {
+        this.goodName = goodName;
+    }
+
+    public Double getTaxRate() {
+        return taxRate;
+    }
+
+    public void setTaxRate(Double taxRate) {
+        this.taxRate = taxRate;
+    }
+
+    public String getPriceTax() {
+        return priceTax;
+    }
+
+    public void setPriceTax(String priceTax) {
+        this.priceTax = priceTax;
+    }
+
+    public String getGoodsTaxno() {
+        return goodsTaxno;
+    }
+
+    public void setGoodsTaxno(String goodsTaxno) {
+        this.goodsTaxno = goodsTaxno;
+    }
+
+    public String getGoodsTypeAbbreviation() {
+        return goodsTypeAbbreviation;
+    }
+
+    public void setGoodsTypeAbbreviation(String goodsTypeAbbreviation) {
+        this.goodsTypeAbbreviation = goodsTypeAbbreviation;
+    }
+
+    public String getBillingContentId() {
+        return billingContentId;
+    }
+
+    public void setBillingContentId(String billingContentId) {
+        this.billingContentId = billingContentId;
+    }
+}

+ 4 - 3
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/InvoiceDownloadService.java

@@ -32,9 +32,9 @@ import java.util.UUID;
 public class InvoiceDownloadService {
 
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
 
 
     @Autowired
@@ -158,6 +158,7 @@ public class InvoiceDownloadService {
                                     workInvoice.setOmsOfdUrl(invoiceInfo.getOfdUrl());
                                     workInvoice.setOmsPdfUrl(invoiceInfo.getPdfUrl());
                                     workInvoice.setOmsXmlUrl(invoiceInfo.getXmlUrl());
+                                    workInvoice.setInvoiceState("5");
                                 }
                                 //修改结果
                                 workInvoiceService.updateOmsUrlById(workInvoice);

+ 76 - 39
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/OMSDisposeService.java

@@ -6,9 +6,14 @@ import com.jeeplus.common.utils.JedisUtils;
 import com.jeeplus.common.utils.StringUtils;
 import com.jeeplus.modules.sys.entity.MainDictDetail;
 import com.jeeplus.modules.sys.utils.DictUtils;
+import com.jeeplus.modules.workclientinfo.dao.WorkClientBankDao;
+import com.jeeplus.modules.workclientinfo.dao.WorkClientInfoDao;
+import com.jeeplus.modules.workclientinfo.entity.WorkClientBank;
+import com.jeeplus.modules.workclientinfo.entity.WorkClientInfo;
 import com.jeeplus.modules.workinvoice.dao.WorkInvoiceDao;
 import com.jeeplus.modules.workinvoice.entity.OMS.OMSAccessTokenInfo;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceTaxClassificationCode;
 import com.jeeplus.modules.workinvoice.utils.HttpPostJsonUtil;
 import com.jeeplus.modules.workinvoice.utils.OMSNationUtil;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,15 +35,19 @@ public class OMSDisposeService {
      * 给accessToken查询的有效时间设置为1天
      */
     private final int seconds = 86400;
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
     //如果接口访问不正确,可以循环访问的次数
     private final int remainRetryTimes = 20;
 
 
     @Autowired
     private WorkInvoiceDao workInvoiceDao;
+    @Autowired
+    private WorkClientInfoDao workClientInfoDao;
+    @Autowired
+    private WorkClientBankDao workClientBankDao;
 
     /**
      * 用于生成开蓝票信息
@@ -54,7 +63,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");
@@ -72,45 +81,73 @@ public class OMSDisposeService {
             OMSNationUtil util = new OMSNationUtil();
             //获取需要开票的发票信息
             WorkInvoice workInvoice = workInvoiceDao.get(workInvoiceId);
-            if(null != workInvoice){
 
-                List<MainDictDetail> billingContentList = DictUtils.getMainDictList("billing_content");
-                for (MainDictDetail dictDetail: billingContentList) {
-                    if(workInvoice.getBillingContent().equals(dictDetail.getValue())){
-                        workInvoice.setBillingContent(dictDetail.getLabel());
-                        break;
+            if(null != workInvoice){
+                if(null != workInvoice.getClient() && StringUtils.isNotBlank(workInvoice.getClient().getId())){
+                    //查询关联的客户开票信息
+                    WorkClientInfo workClientInfo = workClientInfoDao.get(workInvoice.getClient().getId());
+                    if(null != workClientInfo){
+                        workInvoice.setClient(workClientInfo);
+                    }else{
+                        handleInvoiceRetryAllFail("",workInvoiceId, "开票获取发票信息失败"); // 解析失败直接兜底
+                        return;
                     }
+                }else{
+                    handleInvoiceRetryAllFail("",workInvoiceId, "开票获取发票信息失败"); // 解析失败直接兜底
+                    return;
                 }
 
-                //生成开票基础信息
-                String string = util.neatenData(workInvoiceId,workInvoice);
+                WorkClientBank workClientBank = workClientBankDao.get(workInvoice.getBank());
+                if(null != workClientBank){
+                    workInvoice.setBank(workClientBank.getOurBank());
+                }else{
+                    handleInvoiceRetryAllFail("",workInvoiceId, "开票获取发票信息失败"); // 解析失败直接兜底
+                    return;
+                }
 
-                OMSAccessTokenInfo InvoiceTokenInfo = new OMSAccessTokenInfo();
-                InvoiceTokenInfo.setAppId(appId);
-                InvoiceTokenInfo.setAppKey(appKey);
-                InvoiceTokenInfo.setExchangeId(UUID.randomUUID().toString());
-                InvoiceTokenInfo.setAccessToken(accessToken);
-                InvoiceTokenInfo.setData(string);
-                String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
 
-                String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload", jsonInvoiceStr);
-                System.out.println("✅ 订单提交接口返回值:" + jsonInvoicResultStr);
-                map.put("订单接口信息", jsonInvoicResultStr);
+                //判定开票内容是否关联税收编码
+                if(StringUtils.isNotBlank(workInvoice.getBillingContent())){
+                    WorkInvoiceTaxClassificationCode billingContentDetail = workInvoiceDao.getBillingContentDetail(workInvoice);
+                    if(null != billingContentDetail){
+                        workInvoice.setBillingContent(billingContentDetail.getGoodName());
+                        workInvoice.setGoodsTaxno(billingContentDetail.getGoodsTaxno());
+                    }
+                    //生成开票基础信息
+                    String string = util.neatenData(workInvoiceId,workInvoice,billingContentDetail);
+
+                    OMSAccessTokenInfo InvoiceTokenInfo = new OMSAccessTokenInfo();
+                    InvoiceTokenInfo.setAppId(appId);
+                    InvoiceTokenInfo.setAppKey(appKey);
+                    InvoiceTokenInfo.setExchangeId(UUID.randomUUID().toString());
+                    InvoiceTokenInfo.setAccessToken(accessToken);
+                    InvoiceTokenInfo.setData(string);
+                    String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
+
+                    String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload", jsonInvoiceStr);
+                    System.out.println("✅ 订单提交接口返回值:" + jsonInvoicResultStr);
+                    map.put("订单接口信息", jsonInvoicResultStr);
+
+                    // 调用订单上传重试方法(包含所有码值规则)
+                    if(StringUtils.isNotBlank(jsonInvoicResultStr)){
+                        //将上个节点获取的值存到数据库,留作redis崩溃后进行重新获取处理
+                        workInvoice.setOrderForGoodsResultStr(jsonInvoicResultStr);
+                        workInvoiceDao.updateOrderForGoodsResultStrById(workInvoice);
+
+
+                        String finalAccessToken = accessToken;
+                        String finalJsonInvoiceStr = jsonInvoiceStr;
+                        executeOrderUploadRetry(workInvoiceId, remainRetryTimes, jsonInvoicResultStr, finalJsonInvoiceStr, finalAccessToken, map,"accessToken", "blueTicket");
+                    }else{
+                        handleInvoiceRetryAllFail(jsonInvoiceStr,workInvoiceId, "蓝票发送订单生成接口返回值为空,开票失败。节点访问参数为:" + jsonInvoicResultStr); // 解析失败直接兜底
 
-                // 调用订单上传重试方法(包含所有码值规则)
-                if(StringUtils.isNotBlank(jsonInvoicResultStr)){
-                    //将上个节点获取的值存到数据库,留作redis崩溃后进行重新获取处理
-                    workInvoice.setOrderForGoodsResultStr(jsonInvoicResultStr);
-                    workInvoiceDao.updateOrderForGoodsResultStrById(workInvoice);
+                    }
+                }else{
+                    handleInvoiceRetryAllFail("",workInvoiceId, "开票获取发票信息失败"); // 解析失败直接兜底
+                }
 
 
-                    String finalAccessToken = accessToken;
-                    String finalJsonInvoiceStr = jsonInvoiceStr;
-                    executeOrderUploadRetry(workInvoiceId, remainRetryTimes, jsonInvoicResultStr, finalJsonInvoiceStr, finalAccessToken, map,"accessToken", "blueTicket");
-                }else{
-                    handleInvoiceRetryAllFail(jsonInvoiceStr,workInvoiceId, "蓝票发送订单生成接口返回值为空,开票失败。节点访问参数为:" + jsonInvoicResultStr); // 解析失败直接兜底
 
-                }
             }else{
                 handleInvoiceRetryAllFail("",workInvoiceId, "开票获取发票信息失败"); // 解析失败直接兜底
             }
@@ -279,7 +316,7 @@ public class OMSDisposeService {
 
     /**
      * 用于访问接口返回9998时使用,存入Redis供定时任务处理
-     * 硬编码配置:初始重试次数20次,Redis过期时间1天(86400秒)
+     * 硬编码配置:初始重试次数100次,Redis过期时间1天(86400秒)
      * @param jsonInvoiceStr 订单上传的JSON参数
      * @param accessToken    AccessToken
      * @param workInvoiceId        订单号
@@ -288,8 +325,8 @@ public class OMSDisposeService {
      */
     public void saveInvoiceRetryScheduledTaskToRedis(String jsonInvoiceStr ,String accessToken, String workInvoiceId, String getKey, String initiationType) {
         Jedis jedis = null;
-        // 硬编码:初始重试次数20次
-        final int INIT_RETRY_COUNT = 20;
+        // 硬编码:初始重试次数100次
+        final int INIT_RETRY_COUNT = 100;
         // 硬编码:Redis任务过期时间1天(86400秒)
         final int REDIS_EXPIRE_SECONDS = 86400;
 
@@ -358,10 +395,10 @@ public class OMSDisposeService {
                 //将错误信息保存到数据库
                 workInvoice.setOmsErrorMessage(errorMessage);
                 workInvoice.setOmsAccessToken(accessToken);
+                workInvoice.setInvoiceState("1");
                 //修改结果
                 workInvoiceDao.updateAccessTokenErrorById(workInvoice);
 
-                //将业务流程进行撤回
 
                 //通知发起人或者开票管理员
             }
@@ -391,7 +428,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");
@@ -452,7 +489,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");

+ 3 - 3
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceDownloadService.java

@@ -32,9 +32,9 @@ import java.util.UUID;
 public class RedInvoiceDownloadService {
 
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
 
 
     @Autowired

+ 3 - 3
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceScheduledService.java

@@ -30,9 +30,9 @@ import java.util.UUID;
 @Lazy
 public class RedInvoiceScheduledService {
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
 
     @Autowired
     private OMSDisposeService omsDisposeService;

+ 33 - 1
src/main/java/com/jeeplus/modules/workinvoice/service/WorkInvoiceService.java

@@ -45,6 +45,8 @@ import com.jeeplus.modules.workinvoice.dao.WorkInvoiceCloudDao;
 import com.jeeplus.modules.workinvoice.dao.WorkInvoiceDao;
 import com.jeeplus.modules.workinvoice.dao.WorkInvoiceReceiptDao;
 import com.jeeplus.modules.workinvoice.entity.*;
+import com.jeeplus.modules.workinvoice.thread.ApprovalThread;
+import com.jeeplus.modules.workinvoice.thread.RedApprovalThread;
 import com.jeeplus.modules.workinvoicedetail.dao.WorkInvoiceDetailDao;
 import com.jeeplus.modules.workinvoicedetail.entity.WorkInvoiceDetail;
 import com.jeeplus.modules.workinvoicedetail.service.WorkInvoiceDetailService;
@@ -1810,6 +1812,22 @@ public class WorkInvoiceService extends CrudService<WorkInvoiceDao, WorkInvoice>
 							//notifyRole = "财务主任审批";
 							notifyRole = "审批通过";
 							workActivityProcess.setIsApproval("1");
+
+							//需要判定,此处 如果开票金额为正数,则表示是开蓝票,如果是负数,则表示是开红票
+							if(workInvoice.getMoney()>0){
+								//财务审核通过时,需要调用OMS开票接口,用于开票操作。开票完成后,再进行发送成功通知 或者失败通知
+								new ApprovalThread(workInvoice).start();
+							}else{
+								//先获取对应红冲发票的数电票  票号
+								//查询关联红冲发票的开票号
+								if(1 == workInvoice.getRedInvoiceFlag() && StringUtils.isNotBlank(workInvoice.getRedInvoiceRelevancyId())){
+									String invoiceNumberStr = this.getInvoiceNumberStr(workInvoice.getRedInvoiceRelevancyId());
+									workInvoice.setInvoiceNumberStr(invoiceNumberStr);
+								}
+
+								new RedApprovalThread(workInvoice,workInvoice.getInvoiceNumberStr()).start();
+							}
+
 							/*enname = "fpgly";
 							vars.put("fpglyList", auditUsers);
 							vars.put("fpglycount",auditUsers.size());*/
@@ -1824,6 +1842,9 @@ public class WorkInvoiceService extends CrudService<WorkInvoiceDao, WorkInvoice>
 						if ("yes".equals(workInvoice.getAct().getFlag())) {
 							notifyRole = "审批通过";
 							workActivityProcess.setIsApproval("1");
+
+
+
 						} else {
 							notifyRole = "调整申请";
 							workActivityProcess.setIsApproval("2");
@@ -1861,7 +1882,16 @@ public class WorkInvoiceService extends CrudService<WorkInvoiceDao, WorkInvoice>
 			List<User> userList = new ArrayList<>();
 			//ProjectRecords projectRecords = projectRecordsService.getRuralMasters(workInvoice.getProject().getId());
 		if (!state) {
-				users.add(workInvoice.getCreateBy());
+			//将数据流程接点重新归属到审批状态不变,等发票开启之后 进行变更为审核通过,若失败,则变更为暂存状态并发送通知
+			users.add(workInvoice.getCreateBy());
+			//新设定的值,该值表示开票进行中
+			workInvoice.setInvoiceState("12");
+			WorkProjectNotify notify = new WorkProjectNotify();
+			notify.setNotifyId(workInvoice.getId());
+			userList = workProjectNotifyService.readByNotifyId(notify);
+
+
+				/*users.add(workInvoice.getCreateBy());
 				if ("yes".equals(workInvoice.getAct().getFlag())) {
 					title = "项目【"+ projectNameStr +"】发票申请通过";
 					str = "发票金额:" + workInvoice.getMoney() + "(元)。项目【"+ projectNameStr +"】发票申请通过,发票申请编号:"+workInvoice.getNumber();
@@ -1904,6 +1934,8 @@ public class WorkInvoiceService extends CrudService<WorkInvoiceDao, WorkInvoice>
 					}
 				}
 				workActivityProcessService.deleteProcessIdAuditUsers(workInvoice.getProcessInstanceId());
+				*/
+
 			} else {
 				if (StringUtils.isNotBlank(workActivityMenu.getProcessType()) && !workActivityMenu.getProcessType().equals("newWorkInvoiceBranch")) {
 					WorkProjectNotify notify = new WorkProjectNotify();

+ 73 - 0
src/main/java/com/jeeplus/modules/workinvoice/thread/ApprovalThread.java

@@ -0,0 +1,73 @@
+package com.jeeplus.modules.workinvoice.thread;
+
+import com.alibaba.fastjson.JSON;
+import com.google.common.collect.Lists;
+import com.jeeplus.common.config.Global;
+import com.jeeplus.common.oss.OSSClientUtil;
+import com.jeeplus.common.utils.SpringContextHolder;
+import com.jeeplus.modules.projectcontentinfo.entity.ProjectReportData;
+import com.jeeplus.modules.projectcontentinfo.service.ProjectReportDataService;
+import com.jeeplus.modules.ruralprojectrecords.dao.RuralProjectMessageElectronicSealDao;
+import com.jeeplus.modules.ruralprojectrecords.entity.ProjectApprovalSignature;
+import com.jeeplus.modules.ruralprojectrecords.entity.RuralProjectRecords;
+import com.jeeplus.modules.ruralprojectrecords.enums.ProjectStatusEnum;
+import com.jeeplus.modules.ruralprojectrecords.service.RuralProjectMessageService;
+import com.jeeplus.modules.sys.entity.Office;
+import com.jeeplus.modules.sys.entity.Workattachment;
+import com.jeeplus.modules.sys.service.WorkattachmentService;
+import com.jeeplus.modules.sys.utils.UserUtils;
+import com.jeeplus.modules.tools.utils.SignaturePostUtil;
+import com.jeeplus.modules.workactivity.service.WorkActivityProcessService;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
+import com.jeeplus.modules.workinvoice.service.OMS.OMSDisposeService;
+import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
+import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
+import com.jeeplus.modules.workprojectnotify.util.UtilNotify;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author: 徐滕
+ * @create: 2021-12-07 16:36
+ **/
+public class ApprovalThread extends Thread {
+
+    private OMSDisposeService omsDisposeService = SpringContextHolder.getBean(OMSDisposeService.class);
+    private WorkInvoice workInvoice;
+
+
+    public ApprovalThread(WorkInvoice workInvoice)
+    {
+        this.workInvoice = workInvoice;
+    }
+
+    public void run(){
+        String disposeResult = "";
+        Map<String, Object> map = new HashMap<String, Object>();
+        try {
+            //进行签章调用
+            //根据项目id查询是否已经提交过了审定单签章
+            if(null == workInvoice){
+                disposeResult = "查询不到该开票信息";
+                omsDisposeService.handleInvoiceRetryAllFail("","",disposeResult);
+            }
+            if(null!= workInvoice.getOmsOfdUrl()){
+                disposeResult = "该发票已经开过票";
+                omsDisposeService.handleInvoiceRetryAllFail("",workInvoice.getId(),disposeResult);
+            }
+            omsDisposeService.doInvoiceBusiness(map,workInvoice.getId());
+
+        }catch (Exception e){
+            disposeResult = e.getMessage();
+            omsDisposeService.handleInvoiceRetryAllFail("",workInvoice.getId(),disposeResult);
+        }finally {
+
+        }
+
+    }
+}

+ 53 - 0
src/main/java/com/jeeplus/modules/workinvoice/thread/RedApprovalThread.java

@@ -0,0 +1,53 @@
+package com.jeeplus.modules.workinvoice.thread;
+
+import com.jeeplus.common.utils.SpringContextHolder;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
+import com.jeeplus.modules.workinvoice.service.OMS.OMSDisposeService;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: 徐滕
+ * @create: 2021-12-07 16:36
+ **/
+public class RedApprovalThread extends Thread {
+
+    private OMSDisposeService omsDisposeService = SpringContextHolder.getBean(OMSDisposeService.class);
+    private WorkInvoice workInvoice;
+    String originalInvno = "";
+
+
+    public RedApprovalThread(WorkInvoice workInvoice, String originalInvno)
+    {
+        this.workInvoice = workInvoice;
+        this.originalInvno = originalInvno;
+    }
+
+    public void run(){
+        String disposeResult = "";
+        Map<String, Object> map = new HashMap<String, Object>();
+        try {
+            //进行签章调用
+            //根据项目id查询是否已经提交过了审定单签章
+            if(null == workInvoice){
+                disposeResult = "查询不到该开票信息";
+                omsDisposeService.handleInvoiceRetryAllFail("","",disposeResult);
+            }
+            if(null!= workInvoice.getOmsOfdUrl()){
+                disposeResult = "该发票已经开过票";
+                omsDisposeService.handleInvoiceRetryAllFail("",workInvoice.getId(),disposeResult);
+            }
+            omsDisposeService.doAllScenarioRedInvoiceBusiness(map,workInvoice.getId(),originalInvno);
+
+        }catch (Exception e){
+            disposeResult = e.getMessage();
+            omsDisposeService.handleInvoiceRetryAllFail("",workInvoice.getId(),disposeResult);
+
+        }finally {
+
+        }
+
+    }
+}

+ 39 - 22
src/main/java/com/jeeplus/modules/workinvoice/utils/OMSNationUtil.java

@@ -12,6 +12,7 @@ import com.jeeplus.modules.workinvoice.entity.OMS.fastRed.OMSApplyItem;
 import com.jeeplus.modules.workinvoice.entity.OMS.fastRed.OMSFastRedInvoiceInfo;
 import com.jeeplus.modules.workinvoice.entity.OMS.fastRed.OMSRedInvoiceConfirmQueryRequest;
 import com.jeeplus.modules.workinvoice.entity.WorkInvoice;
+import com.jeeplus.modules.workinvoice.entity.WorkInvoiceTaxClassificationCode;
 import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
@@ -86,11 +87,11 @@ public class OMSNationUtil {
     }
 
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
-    private static final String sellerName = Global.getConfig("sellerName");
-    private static final String sellerTaxno = Global.getConfig("sellerTaxno");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
+    private static final String sellerName = Global.getConfig("omsSellerName");
+    private static final String sellerTaxno = Global.getConfig("omsSellerTaxno");
 
     private final String goodstaxno = "109050901"; //税收分类编码(电脑)
     private final String goodsName = "电脑配件"; //税收分类编码(餐饮)
@@ -103,7 +104,7 @@ public class OMSNationUtil {
      * @Param workInvoice   需要开票的信息
      * @return
      */
-    public String neatenData(String workInvoiceId, WorkInvoice workInvoice) {
+    public String neatenData(String workInvoiceId, WorkInvoice workInvoice, WorkInvoiceTaxClassificationCode workInvoiceTaxClassificationCode) {
         List<OrderItem> orderItems = Lists.newArrayList();
 
         InvoiceOMSImportInfo omsImportInfo = new InvoiceOMSImportInfo();
@@ -114,6 +115,8 @@ public class OMSNationUtil {
         //* 开票类型(此处固定是蓝字票)
         //* 01:红字发票 02:蓝字发票,必填
         omsImportInfo.setInvKind("02");
+
+
         //* 发票类型
         //* 01:数电票(增值税专用发票) 02:数电票(普通发票)等
         if(workInvoice.getInvoiceType().equals("1")){
@@ -125,37 +128,51 @@ public class OMSNationUtil {
         //添加购买方信息
         omsImportInfo.setBuyerName("深圳市爱人人餐饮服务有限公司");
         omsImportInfo.setBuyerTaxno("500102203117204029");
-        omsImportInfo.setBuyerAddr(""); //购买方地址
-        omsImportInfo.setBuyerPhone(""); //购买方电话
-        omsImportInfo.setBuyerBank(""); //购买方开户行名称
-        omsImportInfo.setBuyerBankaccount(""); //购买方开户银行账号
-        omsImportInfo.setBuyerNationality(""); //购买方国籍/地区代码
-        omsImportInfo.setBuyerIdcardno(""); //购买方证件号码
-        omsImportInfo.setBuyerIdcartype(""); //购买方证件类型
-        omsImportInfo.setBuyerType(""); //购买方类型(0:企业;1:自然人) 默认企业
-        omsImportInfo.setBuyerCellphone(""); //购买方手机号
-        omsImportInfo.setBuyerEmail(""); //购买方邮箱
+        //omsImportInfo.setBuyerName(workInvoice.getClient().getName());    //购买方名称
+        //omsImportInfo.setBuyerTaxno(workInvoice.getClient().getOrUnicode());  //购买方信用代码
+        omsImportInfo.setBuyerAddr(workInvoice.getClient().getAddress()); //购买方地址
+        omsImportInfo.setBuyerPhone(workInvoice.getClient().getTelephone()); //购买方电话
+        omsImportInfo.setBuyerBank(workInvoice.getBank()); //购买方开户行名称
+        omsImportInfo.setBuyerBankaccount(workInvoice.getBankNumber()); //购买方开户银行账号
+        //omsImportInfo.setBuyerNationality(""); //购买方国籍/地区代码
+        //omsImportInfo.setBuyerIdcardno(""); //购买方证件号码
+        //omsImportInfo.setBuyerIdcartype(""); //购买方证件类型
+        //omsImportInfo.setBuyerCellphone(""); //购买方手机号
+        //omsImportInfo.setBuyerEmail(""); //购买方邮箱
+
+
+        //判定是个人开票 还是企业开票
+        if(workInvoice.getNewDrawer().equals("1")){
+            omsImportInfo.setBuyerType("0"); //购买方类型(0:企业;1:自然人) 默认企业
+        }else if(workInvoice.getNewDrawer().equals("2")){
+            omsImportInfo.setBuyerType("1"); //购买方类型(0:企业;1:自然人) 默认企业
+        }else{
+            omsImportInfo.setBuyerType(""); //购买方类型(0:企业;1:自然人) 默认企业
+        }
+
+
         //omsImportInfo.setRemarks("zzsytdm01,xfsytdm01");
 
 
         OrderItem orderItem = new OrderItem();
         //发票行编号
         orderItem.setLineCode("1");
-        //发票行性质
+        //发票行性质 00(正常行)、01(折扣行)、02(被折扣行)
         orderItem.setLineType("00");
         //添加商品名称
-        orderItem.setGoodsName(workInvoice.getBillingContent());
+        orderItem.setGoodsName(workInvoiceTaxClassificationCode.getGoodName());
         //商品数量
         orderItem.setQty(BigDecimal.valueOf(1));
         //orderItem.setPrice(BigDecimal.valueOf(100.00));
         //默认含税
-        orderItem.setPriceTaxFlag("1"); //含税状态 0不含税;1含税
-        orderItem.setTaxrate(BigDecimal.valueOf(0.01)); //税率
+        orderItem.setPriceTaxFlag(workInvoiceTaxClassificationCode.getPriceTax()); //含税状态 0不含税;1含税
+        orderItem.setTaxrate(BigDecimal.valueOf(workInvoiceTaxClassificationCode.getTaxRate())); //税率
         //orderItem.setAmount(BigDecimal.valueOf(100.00)); //金额
         //orderItem.setTax(BigDecimal.valueOf(1.00));//税额
-        orderItem.setTaxamount(BigDecimal.valueOf(101.00));//含税金额
+        orderItem.setTaxamount(BigDecimal.valueOf(workInvoice.getMoney()));//含税金额
+        //orderItem.setTaxamount(BigDecimal.valueOf(workInvoice.getMoney()));//含税金额
         //orderItem.setGoodstaxno("109050901");//税收分类编码(电脑)
-        orderItem.setGoodstaxno(goodstaxno);//税收分类编码(餐饮)
+        orderItem.setGoodstaxno(workInvoiceTaxClassificationCode.getGoodsTaxno());//税收分类编码(餐饮)
 
         orderItems.add(orderItem);
 

+ 3 - 3
src/main/java/com/jeeplus/modules/workinvoice/utils/RedInvoiceScheduledTask.java

@@ -19,9 +19,9 @@ import java.util.UUID;
 @Component
 public class RedInvoiceScheduledTask {
 
-    private static final String appId = Global.getConfig("appId");
-    private static final String appKey = Global.getConfig("appKey");
-    private static final String deptCode = Global.getConfig("deptCode");
+    private static final String appId = Global.getConfig("omsAppId");
+    private static final String appKey = Global.getConfig("omsAppKey");
+    private static final String deptCode = Global.getConfig("omsDeptCode");
 
 
     // ========== 2. 定时任务入口(8:00-18:00每小时执行) ==========

+ 2 - 2
src/main/resources/jeeplus.properties

@@ -420,6 +420,6 @@ omsAppKey: hyc1
 #组织编码
 omsDeptCode: 500102204228315131
 #销售方纳税人识别号
-sellerTaxno: 500102204228315131
+omsSellerTaxno: 500102204228315131
 #销售方名称
-sellerName: 深圳市松胜电子有限公司
+omsSellerName: 深圳市松胜电子有限公司

+ 8 - 2
src/main/resources/mappings/modules/workinvoice/WorkInvoiceDao.xml

@@ -3340,7 +3340,8 @@
 		UPDATE work_invoice SET
 			oms_access_token_error = #{omsAccessTokenError},
 			oms_access_token = #{omsAccessToken},
-			oms_error_message = #{omsErrorMessage}
+			oms_error_message = #{omsErrorMessage},
+			invoice_state = #{invoiceState}
 		WHERE id = #{id}
 	</update>
 
@@ -3350,7 +3351,8 @@
 			oms_ein_vno = #{omsEinVno},
 			oms_ofd_url = #{omsOfdUrl},
 			oms_pdf_url = #{omsPdfUrl},
-			oms_xml_url = #{omsXmlUrl}
+			oms_xml_url = #{omsXmlUrl},
+			invoice_state = #{invoiceState}
 		WHERE id = #{id}
 	</update>
 
@@ -3368,6 +3370,10 @@
 		WHERE id = #{id}
 	</update>
 
+	<select id="getBillingContentDetail" resultType="com.jeeplus.modules.workinvoice.entity.WorkInvoiceTaxClassificationCode">
+		select * from work_invoice_tax_classification_code where del_flag = 0 and billing_content_id = #{billingContent}
+	</select>
+
 
 
 </mapper>

+ 1 - 0
src/main/webapp/static/common/jeeplus.js

@@ -726,6 +726,7 @@ function getWorkInvoiceAuditState(id)
         case "8":result.label = "changing";result.status="变更中";break;
         case "10":result.label = "signed";result.status="无复核";result.action = false;break;
         case "11":result.label = "cancel";result.status="作废撤回";break;
+        case "12":result.label = "auditing";result.status="开票中";break;
         default:
             result.label = "unknown";result.status="未知";break;
     }

+ 6 - 6
src/main/webapp/webpage/modules/workinvoice/workInvoiceAuditEnd.jsp

@@ -942,25 +942,25 @@
 
 		<div class="form-group layui-row">
 			<div class="form-group-label"><h2>发票明细</h2></div>
-			<div class="layui-item nav-btns">
+			<%--<div class="layui-item nav-btns">
 				<a class="nav-btn nav-btn-add" onclick="addRow('#workAccountList', workAccountListRowIdx, workAccountListTpl);workAccountListRowIdx = workAccountListRowIdx + 1;" title="新增"><i class="fa fa-plus"></i>&nbsp;新增</a>
 				<a href="javascript:void(0)" onclick="openDialogreExcel('导入数据', '${ctx}/workAccount/workAccount/import','90%','90%')" class="nav-btn nav-btn-import" ><i class="fa fa-plus"></i>&nbsp;导入</a>
 				<div id="import" class="hide" style="padding: 5px">
 					<input id="uploadFile" name="file" type="file" style="width:330px"/>导入文件不能超过5M,仅允许导入“xml”格式文件!<br/>  
-						<%--<input type="radio"  name="impType"  checked id="all" value="0">
+						&lt;%&ndash;<input type="radio"  name="impType"  checked id="all" value="0">
 						<label for="all">导入全部</label>
 						<input type="radio"  name="impType" id="noAll" value="1">
-						<label for="noAll">仅导入当前纳税人识别号</label>--%>
+						<label for="noAll">仅导入当前纳税人识别号</label>&ndash;%&gt;
 
 				</div>
 
-			</div>
+			</div>--%>
 			<div class="layui-item layui-col-xs12 form-table-container">
 				<table id="contentTable" class="table table-bordered table-condensed can-edit">
 					<thead>
 					<tr>
 						<th>发票代码</th>
-						<th class="judgment-item"><span class="require-item">*</span>发票号</th>
+						<th class="judgment-item">发票号</th>
 						<th class="judgment-item"><span class="require-item">*</span>开票金额</th>
 						<th width="80px">税率</th>
 						<th width="100px">金额</th>
@@ -987,7 +987,7 @@
 									<input id="workAccountList{{idx}}_code" name="workAccountList[{{idx}}].code" type="text" value="{{row.code}}"    class="form-control number"/>
 								 </td>
 								 <td>
-									<input id="workAccountList{{idx}}_number" name="workAccountList[{{idx}}].number" onchange="checkSame(this)" type="text" value="{{row.number}}"  minlength="8" maxlength="8"  class="form-control number judgment"/>
+									<input id="workAccountList{{idx}}_number" name="workAccountList[{{idx}}].number" readonly placeholder="系统自动生成" style="background-color: #f1f1f1" onchange="checkSame(this)" type="text" value="{{row.number}}"  minlength="8" maxlength="8"  class="form-control number"/>
 									 <input type="hidden" id="workAccountList{{idx}}_oldNumber" value="{{row.number}}"/>
 								 </td>
 								<td>

+ 0 - 39
src/main/webapp/webpage/modules/workinvoice/workInvoiceTwoForm.jsp

@@ -984,19 +984,6 @@
             }
         }
 
-        /*function setV(obj){
-            var a =  $(obj).attr("id");
-            var b = $("#province").val();
-            var c = provinceForShort(b);//开票单位所在省/直辖市简称
-            var date=new Date;
-            var year=date.getFullYear();
-            var month=date.getMonth()+1;
-            month =(month<10 ? "0"+month:month);
-            var mydate = (year.toString()+month.toString());
-            var timestamp="["+mydate+"]";//获取固定格式年月
-			var number = c+timestamp;
-            $("#" +  a ).val(number);
-        }*/
         function setV(obj){
             var a =  $(obj).attr("id");
             var c = "京";
@@ -1046,32 +1033,6 @@
 				multipartUploadWithStsCollection(storeAs, file, attachmentId, attachmentFlag, uploadPath, divId, size);
 			}
 		}
-		/*function insertTemporaryFile(tValue,fileName){
-			var list = "${workInvoice.workAttachments}";
-			var size = (list.split('url')).length-1;
-
-			var temporaryFilePath = tValue;
-			const file = new File([temporaryFilePath], fileName); // 创建File对象
-			var attachmentId = "";
-			var attachmentFlag = "115";
-			var timestamp = new Date().getTime();
-
-			var storeAs = "workInvoice";
-			var uploadPath = "http://gangwan-app.oss-cn-hangzhou.aliyuncs.com/" + storeAs;
-			/!*将这段字符串存到数据库即可*!/
-			var divId = "_attachment";
-			$("#addFile" + divId).show();
-			temporaryMultitest(storeAs, file,temporaryFilePath, attachmentId, attachmentFlag, uploadPath, divId, size);
-		}*/
-
-		/*function num(obj){
-
-			obj.value = obj.value.replace(/[^\d.]/g,""); //清除"数字"和"."以外的字符
-			obj.value = obj.value.replace(/^\./g,""); //验证第一个字符是数字
-			obj.value = obj.value.replace(/\.{2,}/g,"."); //只保留第一个, 清除多余的
-			obj.value = obj.value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
-			obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3'); //只能输入两个小数
-		}*/
 
 		/**
 		 * 数字处理