|
@@ -0,0 +1,189 @@
|
|
|
+package com.gree.mall.manager.schedule;
|
|
|
+
|
|
|
+import cn.hutool.core.date.DateTime;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
+import com.gree.mall.manager.constant.Constant;
|
|
|
+import com.gree.mall.manager.enums.IsYesNoEnum;
|
|
|
+import com.gree.mall.manager.enums.material.PartsRefTypeEnum;
|
|
|
+import com.gree.mall.manager.enums.material.PartsRefundStateEnum;
|
|
|
+import com.gree.mall.manager.enums.material.PayOrderTypeEnum;
|
|
|
+import com.gree.mall.manager.enums.material.WebsitGoodsTypeEnum;
|
|
|
+import com.gree.mall.manager.logic.common.AllInPayLogic;
|
|
|
+import com.gree.mall.manager.plus.entity.WebsitPartsNewRefundManageRecord;
|
|
|
+import com.gree.mall.manager.plus.entity.WebsitPartsOldRefundManageRecord;
|
|
|
+import com.gree.mall.manager.plus.entity.WebsitPartsRefundRecord;
|
|
|
+import com.gree.mall.manager.plus.entity.WebsitSalesPayOrder;
|
|
|
+import com.gree.mall.manager.plus.service.WebsitPartsNewRefundManageRecordService;
|
|
|
+import com.gree.mall.manager.plus.service.WebsitPartsOldRefundManageRecordService;
|
|
|
+import com.gree.mall.manager.plus.service.WebsitPartsRefundRecordService;
|
|
|
+import com.gree.mall.manager.plus.service.WebsitSalesPayOrderService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
+import org.springframework.integration.redis.util.RedisLockRegistry;
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.locks.Lock;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@ConditionalOnProperty(name = "schedule.enable", havingValue = "true", matchIfMissing = true)
|
|
|
+@Component
|
|
|
+@Slf4j
|
|
|
+public class PartsRefundSchedule {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ WebsitSalesPayOrderService websitSalesPayOrderService;
|
|
|
+ @Resource
|
|
|
+ WebsitPartsRefundRecordService websitPartsRefundRecordService;
|
|
|
+ @Resource
|
|
|
+ RedisLockRegistry redisLockRegistry;
|
|
|
+ @Resource
|
|
|
+ AllInPayLogic allInPayLogic;
|
|
|
+ @Resource
|
|
|
+ WebsitPartsNewRefundManageRecordService websitPartsNewRefundManageRecordService;
|
|
|
+ @Resource
|
|
|
+ WebsitPartsOldRefundManageRecordService websitPartsOldRefundManageRecordService;
|
|
|
+
|
|
|
+ @Scheduled(initialDelay = 5000, fixedDelay = 5000)
|
|
|
+ private void newPartsToSalesTasks() throws InterruptedException {
|
|
|
+ //获取分布式锁
|
|
|
+ Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.PARTS_REFUND);
|
|
|
+ if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
|
|
|
+ log.error("获取配件退款锁超时");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 第一步 查询出未执行退款记录
|
|
|
+ List<WebsitPartsRefundRecord> partsRefundRecords = websitPartsRefundRecordService.lambdaQuery()
|
|
|
+ .eq(WebsitPartsRefundRecord::getIsExec, false)
|
|
|
+ .eq(WebsitPartsRefundRecord::getRefundState, PartsRefundStateEnum.WAIT.getKey())
|
|
|
+ .orderByAsc(WebsitPartsRefundRecord::getCreateTime)
|
|
|
+ .list();
|
|
|
+
|
|
|
+ // 第二步 按销售单号分组
|
|
|
+ Map<String, List<WebsitPartsRefundRecord>> groupByIdMap = partsRefundRecords.stream()
|
|
|
+ .collect(Collectors.groupingBy(WebsitPartsRefundRecord::getSalesId));
|
|
|
+
|
|
|
+ // 第三步 遍历销售单号分组
|
|
|
+ for (List<WebsitPartsRefundRecord> partsRefundRecordList : groupByIdMap.values()) {
|
|
|
+ try {
|
|
|
+ // 第四步 查询销售单号对应的支付记录
|
|
|
+ List<WebsitSalesPayOrder> payOrders = websitSalesPayOrderService.lambdaQuery()
|
|
|
+ .eq(WebsitSalesPayOrder::getGoodsType, WebsitGoodsTypeEnum.P.getKey())
|
|
|
+ .eq(WebsitSalesPayOrder::getWebsitId, partsRefundRecordList.get(0).getWebsitId())
|
|
|
+ .eq(WebsitSalesPayOrder::getOrderId, partsRefundRecordList.get(0).getSalesId())
|
|
|
+ .eq(WebsitSalesPayOrder::getPayFlag, IsYesNoEnum.YES.getKey())
|
|
|
+ .list();
|
|
|
+ if (payOrders.size() > 1) {
|
|
|
+ // 异常支付记录有多条
|
|
|
+ this.handleExceptionMethod(partsRefundRecordList, "异常支付记录有多条");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 计算退款总额
|
|
|
+ BigDecimal totalRefundAmount = this.computeRefundAmount(partsRefundRecordList);
|
|
|
+ if (totalRefundAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ this.handleExceptionMethod(partsRefundRecordList, "退款总额必须大于0");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ WebsitSalesPayOrder payRecord = payOrders.get(0);
|
|
|
+
|
|
|
+ String refundId = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
|
|
|
+ // 调用通联退款接口
|
|
|
+ Map<String, String> resMap = allInPayLogic.serviceRefundOrder(payRecord, refundId, totalRefundAmount);
|
|
|
+
|
|
|
+ if ("0000".equals(resMap.get("trxstatus"))) {
|
|
|
+ // 更新支付记录的退款金额 如果退款金额等于支付金额支付记录的支付状态更新为退款
|
|
|
+ payRecord.setRetValue(payRecord.getRetValue().add(totalRefundAmount))
|
|
|
+ .updateById();
|
|
|
+ // 更新记录明细
|
|
|
+ String mchNo = resMap.get("cusid");
|
|
|
+ String refundSerialnumber = resMap.get("reqsn");
|
|
|
+ String refundChnltrxid = resMap.get("chnltrxid");
|
|
|
+ DateTime refundTime = DateUtil.parse(resMap.get("fintime"), "yyyyMMddHHmmss");
|
|
|
+ String refundAccountNo = payRecord.getOpenid();
|
|
|
+ WebsitSalesPayOrder refundOrder = new WebsitSalesPayOrder();
|
|
|
+
|
|
|
+ BeanUtils.copyProperties(payRecord, refundOrder);
|
|
|
+ refundOrder.setId(IdWorker.getIdStr())
|
|
|
+ .setOriginOrderId(payRecord.getOrderId())
|
|
|
+ .setOrderNo(refundId)
|
|
|
+ .setPayTime(refundTime)
|
|
|
+ .setPayValue(totalRefundAmount)
|
|
|
+ .setTransactionId(refundChnltrxid)
|
|
|
+ .setOrderType(PayOrderTypeEnum.R.getKey())
|
|
|
+ .setCreateTime(DateUtil.date())
|
|
|
+ .insert();
|
|
|
+
|
|
|
+
|
|
|
+ this.updateBillRecord(partsRefundRecordList, refundTime, mchNo, refundAccountNo, refundSerialnumber);
|
|
|
+ } else {
|
|
|
+ this.handleExceptionMethod(partsRefundRecordList, resMap.get("errmsg"));
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ this.handleExceptionMethod(partsRefundRecordList, e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ obtain.unlock();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateBillRecord(List<WebsitPartsRefundRecord> partsRefundRecordList, DateTime refundTime, String mchNo,
|
|
|
+ String refundAccountNo, String refundSerialnumber) {
|
|
|
+ for (WebsitPartsRefundRecord partsRefundRecord : partsRefundRecordList) {
|
|
|
+ partsRefundRecord.setRefundState(PartsRefundStateEnum.OK.getKey())
|
|
|
+ .setIsExec(true)
|
|
|
+ .setInfo(refundSerialnumber);
|
|
|
+ String refType = partsRefundRecord.getRefType();
|
|
|
+ if (refType.equals(PartsRefTypeEnum.NEW_REFUND.getKey())) {
|
|
|
+ // 新件返还表
|
|
|
+ websitPartsNewRefundManageRecordService.lambdaUpdate()
|
|
|
+ .set(WebsitPartsNewRefundManageRecord::getRefundTime, refundTime)
|
|
|
+ .set(WebsitPartsNewRefundManageRecord::getRefundState, PartsRefundStateEnum.OK.toString())
|
|
|
+ .set(WebsitPartsNewRefundManageRecord::getRefundMchNo, mchNo)
|
|
|
+ .set(WebsitPartsNewRefundManageRecord::getRefundAccountNo, refundAccountNo)
|
|
|
+ .set(WebsitPartsNewRefundManageRecord::getRefundSerialnumber, refundSerialnumber)
|
|
|
+ .eq(WebsitPartsNewRefundManageRecord::getId, partsRefundRecord.getRecordId())
|
|
|
+ .update();
|
|
|
+ } else if (refType.equals(PartsRefTypeEnum.OLD_REFUND.toString()) || refType.equals(PartsRefTypeEnum.OUTSIDE_TO_SALES.toString())) {
|
|
|
+ // 旧件返还表
|
|
|
+ websitPartsOldRefundManageRecordService.lambdaUpdate()
|
|
|
+ .set(WebsitPartsOldRefundManageRecord::getRefundTime, refundTime)
|
|
|
+ .set(WebsitPartsOldRefundManageRecord::getRefundState, PartsRefundStateEnum.OK.toString())
|
|
|
+ .set(WebsitPartsOldRefundManageRecord::getRefundMchNo, mchNo)
|
|
|
+ .set(WebsitPartsOldRefundManageRecord::getRefundAccountNo, refundAccountNo)
|
|
|
+ .set(WebsitPartsOldRefundManageRecord::getRefundSerialnumber, refundSerialnumber)
|
|
|
+ .eq(WebsitPartsOldRefundManageRecord::getId, partsRefundRecord.getRecordId())
|
|
|
+ .update();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ websitPartsRefundRecordService.updateBatchById(partsRefundRecordList);
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal computeRefundAmount(List<WebsitPartsRefundRecord> partsRefundRecordList) {
|
|
|
+ BigDecimal refundAmount = BigDecimal.ZERO;
|
|
|
+ for (WebsitPartsRefundRecord partsRefundRecord : partsRefundRecordList) {
|
|
|
+ refundAmount = refundAmount.add(partsRefundRecord.getRefundAmount());
|
|
|
+ }
|
|
|
+ return refundAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleExceptionMethod(List<WebsitPartsRefundRecord> partsRefundRecordList, String info) {
|
|
|
+ for (WebsitPartsRefundRecord partsRefundRecord : partsRefundRecordList) {
|
|
|
+ partsRefundRecord.setRefundState(PartsRefundStateEnum.FAIL.toString())
|
|
|
+ .setIsExec(true)
|
|
|
+ .setInfo(info);
|
|
|
+ }
|
|
|
+ websitPartsRefundRecordService.updateBatchById(partsRefundRecordList);
|
|
|
+ }
|
|
|
+}
|