修改订单超时与自动完成

This commit is contained in:
HH 2022-09-10 17:08:33 +08:00
parent 6e4a2ec471
commit e20e08bbe0
6 changed files with 110 additions and 79 deletions

View File

@ -285,12 +285,10 @@ public class OrderDetailServiceImpl implements OrderDetailService {
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
// 暂时先用 synchronized 来避免重复提交 // 暂时先用 synchronized 来避免重复提交
public synchronized void finish(Long orderDetailId) throws BaseAdaPayException { public synchronized void finish(Long orderDetailId) throws BaseAdaPayException {
// 更新订单状态
orderDetailMapper.updateStatus(orderDetailId, OrderStatus.FINISH.code());
// 校验订单 // 校验订单
OrderDetail orderDetail = selectById(orderDetailId); OrderDetail orderDetail = selectById(orderDetailId);
Assert.notNull(orderDetail, "找不到对应的子订单"); Assert.notNull(orderDetail, "找不到对应的子订单");
Assert.isTrue(orderDetail.getOrderStatus().equals(OrderStatus.FINISH.code()), "找不到对应的子订单"); Assert.isTrue(!orderDetail.getOrderStatus().equals(OrderStatus.FINISH.code()), "订单已经是完成状态");
FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId()); FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId());
Assert.notNull(financialMaster, "找不到主财务单"); Assert.notNull(financialMaster, "找不到主财务单");
PaymentDTO payment = financialMasterService.selectPaymentById(financialMaster.getPaymentId()); PaymentDTO payment = financialMasterService.selectPaymentById(financialMaster.getPaymentId());
@ -298,7 +296,8 @@ public class OrderDetailServiceImpl implements OrderDetailService {
FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(orderDetailId); FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(orderDetailId);
Assert.notNull(financialDetail, "找不到子财务单"); Assert.notNull(financialDetail, "找不到子财务单");
Assert.isTrue(financialDetail.getPayStatus() == 1, "订单不是“已支付”状态"); Assert.isTrue(financialDetail.getPayStatus() == 1, "订单不是“已支付”状态");
// 更新订单状态
orderDetailMapper.updateStatus(orderDetailId, OrderStatus.FINISH.code());
if (BigDecimal.ZERO.compareTo(financialDetail.getPayMoney()) > -1) { if (BigDecimal.ZERO.compareTo(financialDetail.getPayMoney()) > -1) {
logger.info("子财务单[code={}]支付金额<=0不需要分账", financialDetail.getCode()); logger.info("子财务单[code={}]支付金额<=0不需要分账", financialDetail.getCode());
// 支付金额<=0的话 不需要走下面的流程了 // 支付金额<=0的话 不需要走下面的流程了

View File

@ -1,33 +0,0 @@
package com.ghy.payment.domain;
import lombok.Data;
import java.util.Date;
/**
* 订单扣款记录
*
* @author HH 2022/8/4
*/
@Data
public class OrderFineRecord {
private Long id;
private Long orderDetailId;
private Integer fineType;
private Integer orderStatus;
private Date createTime;
public OrderFineRecord() {
}
public OrderFineRecord(Long orderDetailId, Integer fineType, Integer orderStatus) {
this.orderDetailId = orderDetailId;
this.fineType = fineType;
this.orderStatus = orderStatus;
}
}

View File

@ -0,0 +1,44 @@
package com.ghy.payment.domain;
import lombok.Data;
import java.util.Date;
/**
* 订单超时扣款记录表
*
* @author HH 2022/8/4
*/
@Data
public class OrderTimeoutRecord {
private Long id;
/**
* 子订单ID
*/
private Long orderDetailId;
/**
* 超时时的订单状态
*/
private Integer orderStatus;
/**
* 扣款状态 0未扣款 1已扣款
*/
private Integer fineStatus;
/**
* 创建时间
*/
private Date createTime;
public OrderTimeoutRecord() {
}
public OrderTimeoutRecord(Long orderDetailId, Integer orderStatus) {
this.orderDetailId = orderDetailId;
this.orderStatus = orderStatus;
}
}

View File

@ -1,6 +1,6 @@
package com.ghy.payment.mapper; package com.ghy.payment.mapper;
import com.ghy.payment.domain.OrderFineRecord; import com.ghy.payment.domain.OrderTimeoutRecord;
import java.util.List; import java.util.List;
@ -9,7 +9,9 @@ import java.util.List;
*/ */
public interface OrderFineRecordMapper { public interface OrderFineRecordMapper {
List<OrderFineRecord> selectList(OrderFineRecord orderFineRecord); List<OrderTimeoutRecord> selectList(OrderTimeoutRecord orderTimeoutRecord);
int insert(OrderFineRecord orderFineRecord); int insert(OrderTimeoutRecord orderTimeoutRecord);
int update(OrderTimeoutRecord orderTimeoutRecord);
} }

View File

@ -4,20 +4,20 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ghy.payment.mapper.OrderFineRecordMapper"> <mapper namespace="com.ghy.payment.mapper.OrderFineRecordMapper">
<resultMap id="OrderFineRecordResult" type="com.ghy.payment.domain.OrderFineRecord"> <resultMap id="OrderFineRecordResult" type="com.ghy.payment.domain.OrderTimeoutRecord">
<id property="id" column="id"/> <id property="id" column="id"/>
<result property="orderDetailId" column="order_detail_id"/> <result property="orderDetailId" column="order_detail_id"/>
<result property="fineType" column="fine_type"/> <result property="fineStatus" column="fine_status"/>
<result property="orderStatus" column="order_status"/> <result property="orderStatus" column="order_status"/>
<result property="createTime" column="create_time"/> <result property="createTime" column="create_time"/>
</resultMap> </resultMap>
<sql id="selectOrderFineRecord"> <sql id="selectOrderFineRecord">
SELECT id, order_detail_id, fine_type, order_status, create_time SELECT id, order_detail_id, fine_status, order_status, create_time
FROM order_fine_record FROM order_timeout_record
</sql> </sql>
<select id="selectList" parameterType="com.ghy.payment.domain.OrderFineRecord" <select id="selectList" parameterType="com.ghy.payment.domain.OrderTimeoutRecord"
resultMap="OrderFineRecordResult"> resultMap="OrderFineRecordResult">
<include refid="selectOrderFineRecord"/> <include refid="selectOrderFineRecord"/>
<where> <where>
@ -30,9 +30,15 @@
</where> </where>
</select> </select>
<insert id="insert" parameterType="com.ghy.payment.domain.OrderFineRecord" useGeneratedKeys="true" <insert id="insert" parameterType="com.ghy.payment.domain.OrderTimeoutRecord" useGeneratedKeys="true"
keyProperty="id"> keyProperty="id">
INSERT INTO order_fine_record (order_detail_id, fine_type, order_status) INSERT INTO order_timeout_record (order_detail_id, fine_status, order_status)
VALUES (#{orderDetailId}, #{fineType}, #{orderStatus}) VALUES (#{orderDetailId}, #{fineStatus}, #{orderStatus})
</insert> </insert>
<update id="update">
UPDATE order_timeout_record SET fine_status = #{fineStatus}
WHERE id = #{id}
</update>
</mapper> </mapper>

View File

@ -7,7 +7,7 @@ import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderDetailService; import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService; import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.OrderFineRecord; import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper; import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.FinancialDetailService; import com.ghy.payment.service.FinancialDetailService;
import com.ghy.quartz.service.OrderService; import com.ghy.quartz.service.OrderService;
@ -22,7 +22,6 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
@ -44,7 +43,7 @@ public class OrderServiceImpl implements OrderService {
/** /**
* 需要超时扣款的订单状态 * 需要超时扣款的订单状态
*/ */
@Value("${order.timeout.status:-4,-3,-2,1,2,3}") @Value("${order.timeout.status:-4,-3,-2,1,2}")
private List<Integer> timeoutOrderStatus; private List<Integer> timeoutOrderStatus;
@Resource @Resource
@ -60,49 +59,63 @@ public class OrderServiceImpl implements OrderService {
@Override @Override
public void overTimeOrder(String orderStatus) { public void overTimeOrder(String orderStatus) {
LocalDateTime now = LocalDateTime.now(); // 这是半小时前的时间
int nowDay = now.getDayOfMonth(); Date halfHour = new Date(System.currentTimeMillis() - 30 * 60 * 1000);
int nowHour = now.getHour(); // 这是4小时前的时间
if (nowHour > 17 || nowHour < 9) { Date fourHour = new Date(System.currentTimeMillis() - 4 * 60 * 60 * 1000);
// 如果处于休息时间 定时任务不执行
return;
}
// 查询符合超时的单 // 查询符合超时的单
List<OrderDetail> orders = orderDetailService.selectByStatus(timeoutOrderStatus); List<OrderDetail> orders = orderDetailService.selectByStatus(timeoutOrderStatus);
for (OrderDetail order : orders) { for (OrderDetail order : orders) {
Date updateTime = order.getUpdateTime(); if (order.getOrderStatus().equals(OrderStatus.SERVER.code())) {
Calendar instance = Calendar.getInstance(); // 服务中状态要按预计上门时间计算超时 4h超时并且扣款
instance.setTime(updateTime); if (order.getExpectTimeStart().before(fourHour)) {
if (instance.get(Calendar.DAY_OF_MONTH) == nowDay) { executor.execute(() -> orderTimeout(order, true));
// 如果订单更新的时间是今天
if (System.currentTimeMillis() - updateTime.getTime() > HOUR_TIME_MILLIS * 4) {
// 并且距离上一次更新时间已经超过4h 则判定超时
executor.execute(() -> orderTimeout(order));
} }
} else { } else if (timeoutOrderStatus.contains(order.getOrderStatus())) {
// 如果订单更新的时间不是今天 // 其它状态用update_time判断超时 30min超时 4h扣款
if (System.currentTimeMillis() - updateTime.getTime() > HOUR_TIME_MILLIS * 19) { if (order.getUpdateTime().before(fourHour)) {
// 并且距离上一次更新时间已经超过15h 则判定超时 executor.execute(() -> orderTimeout(order, true));
executor.execute(() -> orderTimeout(order)); } else if (order.getUpdateTime().before(halfHour)) {
executor.execute(() -> orderTimeout(order, false));
} }
} }
} }
} }
/**
* 处理订单超时与扣款
*
* @param order 子订单信息
* @param fine 是否需要扣款
*/
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void orderTimeout(OrderDetail order) { public void orderTimeout(OrderDetail order, boolean fine) {
// 查询扣款记录 如果已经扣过了 就不处理了 OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getOrderStatus());
OrderFineRecord orderFineRecord = new OrderFineRecord(order.getId(), 1, order.getOrderStatus()); List<OrderTimeoutRecord> records = orderFineRecordMapper.selectList(record);
List<OrderFineRecord> records = orderFineRecordMapper.selectList(orderFineRecord); if (CollectionUtils.isEmpty(records)) {
if (!CollectionUtils.isEmpty(records)) { // 如果没有扣款记录 则保存一条扣款记录
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
} else {
record = records.get(0);
}
if (!fine) {
// 不需要扣款
return;
}
if (record.getFineStatus() == 1) {
// 如果已经扣款 就不需要往下走了
return; return;
} }
// 保存一条扣款记录 // 把超时记录的扣款状态改为1
orderFineRecordMapper.insert(orderFineRecord); record.setFineStatus(1);
orderFineRecordMapper.update(record);
//下面是扣款逻辑
// 从子订单对应的财务单里扣除2元 // 从子订单对应的财务单里扣除2元
FinancialDetail orderFinancial = financialDetailService.selectByOrderDetailId(order.getId()); FinancialDetail orderFinancial = financialDetailService.selectByOrderDetailId(order.getId());
orderFinancial.setPayMoney(orderFinancial.getPayMoney().subtract(TIMEOUT_MONEY)); orderFinancial.setPayMoney(orderFinancial.getPayMoney().subtract(TIMEOUT_MONEY));
@ -145,7 +158,7 @@ public class OrderServiceImpl implements OrderService {
executor.execute(() -> { executor.execute(() -> {
try { try {
orderMasterService.finish(orderMaster.getId()); orderMasterService.finish(orderMaster.getId());
}catch (Exception e){ } catch (Exception e) {
logger.error("主订单 Finish 失败", e); logger.error("主订单 Finish 失败", e);
} }
}); });