一、 application.yml配置
invoiceCancelNotDeductResult: true #获取取消不抵扣结果任务开关
invoiceCancelNotDeductResultCron: 0 0/1 * * * ? #获取取消不抵扣结果cron表达式。修改cron,需要修改锁有效期
invoiceCancelNotDeductResultLockExpire: 178 #获取取消不抵扣结果锁有效期,3*60-2
二. 定时任务
@Component
public class InvoiceCancelNotDeductResultScheduled {
private static Logger logger = LoggerFactory.getLogger(InvoiceCancelNotDeductResultScheduled.class);
@Autowired
private InvoiceNotDeductScheduledService invoiceNotDeductScheduledService;
@Autowired
private ScheduledControll scheduledControll;
@Value("${scheduled.invoiceCancelNotDeductResult}")
private boolean invoiceCancelNotDeductResultFlag;
/**
* 发起不抵扣结果反馈锁有效期,2*60-2
*/
@Value("${scheduled.invoiceCancelNotDeductResultLockExpire}")
private String invoiceCancelNotDeductResultLockExpire;
/**
* 发起取消不抵扣结果反馈,获取任务号,3分钟一次
* TODO:修改定时任务时间需要同步修改锁定的有效期。
*/
@Scheduled(cron = "${scheduled.invoiceCancelNotDeductResultCron}")
public void invoiceCancelNotDeductResult() {
try {
String requestId = String.valueOf(UUID.randomUUID());
MDC.put("requestId", requestId);
//获取配置文件开关
if (!invoiceCancelNotDeductResultFlag) {
logger.info("InvoiceCancelNotDeductResultScheduled 开关未开启,不执行发起取消不抵扣结果反馈定时任务");
return;
}
//获取锁(定时任务支持集群,防止重复执行定时任务)
if (StringUtils.isNotEmpty(invoiceCancelNotDeductResultLockExpire) && RegexMatchUtils.numericalMatch(invoiceCancelNotDeductResultLockExpire) && !scheduledControll.getInvoiceNotDeductResultScheduledLock(Integer.parseInt(invoiceCancelNotDeductResultLockExpire))) {
logger.info("InvoiceCancelNotDeductResultScheduled 未能获取发起取消不抵扣结果反馈锁,不执行发起取消不抵扣结果反馈定时任务");
return;
}
logger.info("定时任务++++++InvoiceCancelNotDeductResultScheduled 发起取消不抵扣结果反馈定时任务开始**************");
long startTime = System.currentTimeMillis();
invoiceNotDeductScheduledService.cancelNotDeductResultRet();
logger.info("定时任务++++++++++InvoiceCancelNotDeductResultScheduled 发起取消不抵扣结果反馈定时任务结束,耗时:{}ms", System.currentTimeMillis() - startTime);
} catch (Exception e) {
//日志
logger.info("InvoiceCancelNotDeductResultScheduled system error:", e);
} finally {
MDC.clear();
}
}
}
三. 具体实现
- 定时任务service接口
public interface InvoiceNotDeductScheduledService {
/**
* 发票不抵扣结果反馈
*/
void notDeductResultRet();
/**
* 发票取消不抵扣结果反馈
*/
void cancelNotDeductResultRet();
}
2… 定时任务实现类
package com.baiwang.platform.custom.service.impl.notdeduct;
import com.baiwang.platform.custom.common.enums.NotDeductEnum;
import com.baiwang.platform.custom.common.model.NotDeductRequest;
import com.baiwang.platform.custom.common.model.TScmVatNotDeduct;
import com.baiwang.platform.custom.service.notdeduct.ITScmVatNotDeductService;
import com.baiwang.platform.custom.service.notdeduct.InvoiceNotDeductScheduledService;
import com.baiwang.platform.custom.service.notdeduct.NotDeductBaseService;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @ClassName InvoiceNotDeductScheduledServiceImpl
* @Description 发票不抵扣定时任务
* @Author yuan_wm
* @Date 2019/12/10 下午3:27
* @Version 1.0
**/
@Service
public class InvoiceNotDeductScheduledServiceImpl implements InvoiceNotDeductScheduledService {
private static final Logger logger = LoggerFactory.getLogger(InvoiceNotDeductScheduledServiceImpl.class);
@Autowired
private NotDeductBaseService notDeductBaseService;
@Autowired
private ITScmVatNotDeductService notDeductService;
@Override
public void cancelNotDeductResultRet() {
// 获取发起取消不抵扣结果反馈的发票
NotDeductRequest req = new NotDeductRequest();
req.setDeductStatus(NotDeductEnum.NOT_DEDUCT_CANCLEING.getCode());// 4-取消不抵扣中
PageInfo<TScmVatNotDeduct> page = notDeductService.queryCancelNotDeductListByCondition(req, 1, 1000);
List<TScmVatNotDeduct> notDeductList = page.getList();
if (notDeductList == null || notDeductList.size() == 0) {
return;
}
cancelNotDeductResultRetLatch(notDeductList);
}
private void cancelNotDeductResultRetLatch(List<TScmVatNotDeduct> notDeductList) {
int threshold = 50;
int size = notDeductList.size(); // 根据状态值获取的记录数
int count = size / threshold + (size % threshold == 0 ? 0 : 1);
CountDownLatch latch = new CountDownLatch(count);
try {
while (notDeductList.size() >= threshold) {
List<TScmVatNotDeduct> newList = new ArrayList<>();
for (int i = 0; i < threshold; i++) {
newList.add(notDeductList.get(0));
notDeductList.remove(0);
}
notDeductBaseService.executeCancelNotDeductResultRet(newList, latch);
}
if (notDeductList.size() > 0) {
notDeductBaseService.executeCancelNotDeductResultRet(notDeductList, latch);
}
latch.await();
} catch (Exception e) {
logger.error("cancelNotDeductResultRetLatch error", e);
}
}
}
- 具体业务接口
public interface NotDeductBaseService {
Future<String> executeCancelNotDeductResultRet(List<TScmVatNotDeduct> notDeductList, CountDownLatch latch);
}
- 具体业务实现类
package com.baiwang.platform.custom.service.impl.notdeduct;
import com.baiwang.bop.respose.entity.input.ResultResponse;
import com.baiwang.platform.custom.common.enums.NotDeductEnum;
import com.baiwang.platform.custom.common.model.NotDeductRequest;
import com.baiwang.platform.custom.common.model.TScmVatNotDeduct;
import com.baiwang.platform.custom.common.result.RestFulApiContants;
import com.baiwang.platform.custom.dao.CheckDeductDao;
import com.baiwang.platform.custom.dao.TScmVatDeductInfoMapper;
import com.baiwang.platform.custom.dao.TScmVatMainMapper;
import com.baiwang.platform.custom.dao.domain.TScmVatMain;
import com.baiwang.platform.custom.integration.bwcloud.JxChannelUtils;
import com.baiwang.platform.custom.service.notdeduct.ITScmVatNotDeductService;
import com.baiwang.platform.custom.service.notdeduct.NotDeductBaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
@Service
public class NotDeductBaseServiceImpl implements NotDeductBaseService {
private static final Logger logger = LoggerFactory.getLogger(NotDeductBaseServiceImpl.class);
@Autowired
private JxChannelUtils jxChannelUtils;
@Autowired
private ITScmVatNotDeductService notDeductService;
@Autowired
private TScmVatMainMapper tScmVatMainMapper;
@Autowired
private CheckDeductDao checkDeductDao;
@Autowired
private TScmVatDeductInfoMapper notDeductInfoMapper;
@Async
@Override
public Future<String> executeCancelNotDeductResultRet(List<TScmVatNotDeduct> notDeductList, CountDownLatch latch) {
try {
TScmVatMain t = new TScmVatMain();
for (TScmVatNotDeduct notDeduct : notDeductList) {
ResultResponse deductibleResponse = jxChannelUtils.deductibleResult(notDeduct.getBuyerTaxno(),
notDeduct.getCancelNoDeductTaskNo(), notDeduct.getInvKind(), notDeduct.getInvNum());
String code = deductibleResponse.getResultCode();
if ("1".equals(code)) {
Date d = new Date();
//取消不抵扣成功,置为5
notDeduct.setDeductStatus(NotDeductEnum.NOT_DEDUCT_CANCLE_SUCCESS.getCode());//5-取消不抵扣成功
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
notDeduct.setResponseTime(formatter.format(d));
notDeduct.setResponseCode(code);
notDeductService.updateByPrimaryKeySelective(notDeduct);
// 更新主表状态
NotDeductRequest notDeductRequest = new NotDeductRequest();
notDeductRequest.setPreDeductFlag(notDeduct.getPreDeductFlag());
notDeductRequest.setInvKind(notDeduct.getInvKind());
notDeductRequest.setInvNum(notDeduct.getInvNum());
notDeductRequest.setBuyerTaxno(notDeduct.getBuyerTaxno());
HashMap<String, Object> preDeductFlagMap = new HashMap();
preDeductFlagMap.put("ids", notDeductRequest.getIds());
preDeductFlagMap.put("preDeductFlag", RestFulApiContants.PRE_DEDU_FLAG_INIT);
int j = notDeductInfoMapper.changePreDeductFlag(preDeductFlagMap);
} else if ("0".equals(code) || "6".equals(code)) {
//日志 : 任务执行中
if (logger.isInfoEnabled()) {
logger.info(String.format("executeNotDeductResultRet 发票代码:%s 发票号码:%s taskno:%s任务执行中", notDeduct.getInvKind(), notDeduct.getInvNum(), notDeduct.getConfirmNoDeductTaskNo()));
}
} else {
notDeduct.setDeductStatus(NotDeductEnum.NOT_DEDUCT_SUCCESS.getCode());//2.不抵扣成功
notDeduct.setResponseCode(code);
notDeductService.updateByPrimaryKeySelective(notDeduct);
}
}
} catch (Exception e) {
logger.error("取消不抵扣定时任务失败:{}",e.getMessage());
}
finally {
latch.countDown();
}
return new AsyncResult<>("executeNotDeductResultRet accomplished!");
}
}