feat(health):新增用户取消/退款订单的功能

This commit is contained in:
JIAN
2024-09-16 22:35:23 +08:00
parent a48fae5d30
commit db85c197a8
17 changed files with 365 additions and 86 deletions

View File

@@ -1,6 +1,5 @@
package com.jzo2o.health.controller.user; package com.jzo2o.health.controller.user;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.health.model.dto.response.OrdersDetailResDTO; import com.jzo2o.health.model.dto.response.OrdersDetailResDTO;
import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO;
import com.jzo2o.health.service.IOrderManagerService; import com.jzo2o.health.service.IOrderManagerService;
@@ -40,6 +39,6 @@ public class OrdersQueryController {
@ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class) @ApiImplicitParam(name = "id", value = "订单id", required = true, dataTypeClass = Long.class)
}) })
public OrdersDetailResDTO detail(@PathVariable("id") Long id) { public OrdersDetailResDTO detail(@PathVariable("id") Long id) {
return BeanUtils.toBean(orderManagerService.getById(id), OrdersDetailResDTO.class); return orderManagerService.getOrderById(id);
} }
} }

View File

@@ -1,6 +1,8 @@
package com.jzo2o.health.controller.user; package com.jzo2o.health.controller.user;
import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO; import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO;
import com.jzo2o.health.service.IOrderCancelService;
import com.jzo2o.health.service.IOrderRefundService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
@@ -8,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/** /**
* @author itcast * @author itcast
*/ */
@@ -15,14 +19,20 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/user/orders") @RequestMapping("/user/orders")
@Api(tags = "用户端 - 取消订单退款相关接口") @Api(tags = "用户端 - 取消订单退款相关接口")
public class OrdersRefundController { public class OrdersRefundController {
@Resource
private IOrderCancelService orderCancelService;
@Resource
private IOrderRefundService orderRefundService;
@PutMapping("/cancel") @PutMapping("/cancel")
@ApiOperation("订单取消") @ApiOperation("订单取消")
public void cancel(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { public void cancel(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) {
orderCancelService.cancelOrder(ordersCancelReqDTO);
} }
@PutMapping("/refund") @PutMapping("/refund")
@ApiOperation("订单退款") @ApiOperation("订单退款")
public void refund(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) { public void refund(@RequestBody OrdersCancelReqDTO ordersCancelReqDTO) {
orderRefundService.refundOrder(ordersCancelReqDTO);
} }
} }

View File

@@ -1,58 +0,0 @@
package com.jzo2o.health.handler;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.health.properties.OrdersJobProperties;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* 订单相关定时任务
*
* @author itcast
* @create 2023/9/2 16:44
**/
@Slf4j
@Component
public class OrdersHandler {
@Resource
private RefundRecordApi refundRecordApi;
//解决同级方法调用,事务失效问题
@Resource
private OrdersHandler orderHandler;
@Resource
private OrdersJobProperties ordersJobProperties;
/**
* 支付超时取消订单
* 每分钟执行一次
*/
@XxlJob(value = "cancelOverTimePayOrder")
public void cancelOverTimePayOrder() {
}
/**
* 订单退款异步任务
*/
@XxlJob(value = "handleRefundOrders")
public void handleRefundOrders() {
}
/**
* 订单退款处理
*
* @param id 订单id
* @param executionResultResDTO 第三方退款信息
*/
@Transactional(rollbackFor = Exception.class)
public void refundOrder(Long id, ExecutionResultResDTO executionResultResDTO) {
}
}

View File

@@ -0,0 +1,40 @@
package com.jzo2o.health.job;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.health.model.domain.OrdersRefund;
import com.jzo2o.health.properties.OrdersJobProperties;
import com.jzo2o.health.service.IOrderRefundService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* 订单退款任务
* @author JIAN
*/
@Slf4j
@Component
@SuppressWarnings("unused")
public class OrderRefundJob {
@Resource
private IOrderRefundService orderRefundService;
@Resource
private OrdersJobProperties ordersJobProperties;
/**
* 订单退款异步任务
*/
@XxlJob(value = "handleRefundOrders")
public void handleRefundOrders() {
List<OrdersRefund> latestRefundInfo = orderRefundService.getLatestRefundInfo(ordersJobProperties.getRefundOrderCount());
if (CollUtils.isEmpty(latestRefundInfo)) {
log.info("没有需要退款的订单");
}
latestRefundInfo.forEach(refundInfo -> orderRefundService.refundOrder(refundInfo));
}
}

View File

@@ -1,23 +1,25 @@
package com.jzo2o.health.model.domain; package com.jzo2o.health.model.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/** /**
* <p> * <p>
* 订单取消表 * 订单取消表
* </p> * </p>
*
* @author itcast * @author itcast
* @since 2023-11-07 * @since 2023-11-07
*/ */
@Data @Data
@Builder
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@TableName("orders_cancelled") @TableName("orders_cancelled")
@@ -28,7 +30,7 @@ public class OrdersCancelled implements Serializable {
/** /**
* 订单id * 订单id
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.NONE)
private Long id; private Long id;
/** /**
@@ -65,6 +67,4 @@ public class OrdersCancelled implements Serializable {
* 更新时间 * 更新时间
*/ */
private LocalDateTime updateTime; private LocalDateTime updateTime;
} }

View File

@@ -1,24 +1,26 @@
package com.jzo2o.health.model.domain; package com.jzo2o.health.model.domain;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* <p> * <p>
* 订单退款表 * 订单退款表
* </p> * </p>
*
* @author itcast * @author itcast
* @since 2023-11-07 * @since 2023-11-07
*/ */
@Data @Data
@Builder
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@Accessors(chain = true) @Accessors(chain = true)
@TableName("orders_refund") @TableName("orders_refund")
@@ -29,7 +31,7 @@ public class OrdersRefund implements Serializable {
/** /**
* 订单id * 订单id
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.NONE)
private Long id; private Long id;
/** /**
@@ -46,6 +48,4 @@ public class OrdersRefund implements Serializable {
* 创建时间 * 创建时间
*/ */
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@@ -1,6 +1,8 @@
package com.jzo2o.health.model.dto.response; package com.jzo2o.health.model.dto.response;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.jzo2o.health.enums.OrderPayStatusEnum;
import com.jzo2o.health.enums.OrderStatusEnum;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@@ -30,13 +32,13 @@ public class OrdersDetailResDTO {
* 订单状态0未支付100待体检200已体检300已关闭400已取消 * 订单状态0未支付100待体检200已体检300已关闭400已取消
*/ */
@ApiModelProperty("订单状态0未支付100待体检200已体检300已关闭400已取消") @ApiModelProperty("订单状态0未支付100待体检200已体检300已关闭400已取消")
private Integer orderStatus; private OrderStatusEnum orderStatus;
/** /**
* 支付状态0未支付1已支付2退款中3退款成功4退款失败 * 支付状态0未支付1已支付2退款中3退款成功4退款失败
*/ */
@ApiModelProperty("支付状态0未支付1已支付2退款中3退款成功4退款失败") @ApiModelProperty("支付状态0未支付1已支付2退款中3退款成功4退款失败")
private Integer payStatus; private OrderPayStatusEnum payStatus;
/** /**
* 套餐id * 套餐id

View File

@@ -2,10 +2,20 @@ package com.jzo2o.health.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.jzo2o.health.model.domain.OrdersCancelled; import com.jzo2o.health.model.domain.OrdersCancelled;
import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO;
/** /**
* 取消订单相关业务层 * 取消订单相关业务层
* @author JIAN * @author JIAN
*/ */
public interface IOrderCancelService extends IService<OrdersCancelled> { public interface IOrderCancelService extends IService<OrdersCancelled> {
/**
* 用户取消订单
*/
void cancelOrder(OrdersCancelReqDTO ordersCancelReqDTO);
/**
* 取消订单(内部使用)
*/
void cancelOrder(OrdersCancelled ordersCancelled);
} }

View File

@@ -12,7 +12,7 @@ import com.jzo2o.health.model.domain.Orders;
* @author itcast * @author itcast
* @since 2023-08-02 * @since 2023-08-02
*/ */
public interface IOrdersCommonService extends IService<Orders> { public interface IOrderCommonService extends IService<Orders> {
/** /**
* 更新指定id订单的状态 * 更新指定id订单的状态
*/ */

View File

@@ -5,6 +5,7 @@ import com.jzo2o.common.model.PageResult;
import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO;
import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO;
import com.jzo2o.health.model.dto.response.OrdersDetailResDTO;
import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO;
import java.util.List; import java.util.List;
@@ -28,4 +29,9 @@ public interface IOrderManagerService extends IService<Orders> {
* 管理端查询订单详情 * 管理端查询订单详情
*/ */
AdminOrdersDetailResDTO getAggregationInfo(Long id); AdminOrdersDetailResDTO getAggregationInfo(Long id);
/**
* 用户端获取订单详情
*/
OrdersDetailResDTO getOrderById(Long id);
} }

View File

@@ -0,0 +1,29 @@
package com.jzo2o.health.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jzo2o.health.model.domain.OrdersRefund;
import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO;
import java.util.List;
/**
* 订单退款相关业务层
* @author JIAN
*/
public interface IOrderRefundService extends IService<OrdersRefund> {
/**
* 用户订单退款
*/
void refundOrder(OrdersCancelReqDTO ordersCancelReqDTO);
/**
* 调用API退款(内部使用)
*/
void refundOrder(OrdersRefund ordersRefund);
/**
* 获取最新的订单退款信息
* @param count 处理数量
*/
List<OrdersRefund> getLatestRefundInfo(Integer count);
}

View File

@@ -1,10 +1,26 @@
package com.jzo2o.health.service.impl; package com.jzo2o.health.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.jzo2o.common.expcetions.DBException;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.health.enums.OrderPayStatusEnum;
import com.jzo2o.health.enums.OrderStatusEnum;
import com.jzo2o.health.mapper.OrdersCancelledMapper; import com.jzo2o.health.mapper.OrdersCancelledMapper;
import com.jzo2o.health.model.OrderUpdateStatusDTO;
import com.jzo2o.health.model.UserThreadLocal;
import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.model.domain.OrdersCancelled; import com.jzo2o.health.model.domain.OrdersCancelled;
import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO;
import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCancelService;
import com.jzo2o.health.service.IOrderCommonService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/** /**
* 取消订单相关业务层实现 * 取消订单相关业务层实现
@@ -12,4 +28,52 @@ import org.springframework.stereotype.Service;
*/ */
@Service @Service
public class OrderCancelServiceImpl extends ServiceImpl<OrdersCancelledMapper, OrdersCancelled> implements IOrderCancelService { public class OrderCancelServiceImpl extends ServiceImpl<OrdersCancelledMapper, OrdersCancelled> implements IOrderCancelService {
@Resource
private IOrderCommonService orderCommonService;
@Override
@Transactional
public void cancelOrder(OrdersCancelReqDTO ordersCancelReqDTO) {
CurrentUserInfo currentUser = UserThreadLocal.currentUser();
if (ObjectUtils.isEmpty(currentUser) || ObjectUtils.isEmpty(currentUser.getId())) {
throw new ForbiddenOperationException("无法获取用户信息无法取消");
}
Long orderId = ordersCancelReqDTO.getId();
Orders orders = orderCommonService.getById(orderId);
if (ObjectUtils.isEmpty(orders)) {
throw new ForbiddenOperationException("订单不存在无法取消");
}
if (orders.getOrderStatus() != OrderStatusEnum.NO_PAY || orders.getPayStatus() != OrderPayStatusEnum.NO_PAY) {
throw new ForbiddenOperationException("订单状态错误无法取消");
}
this.cancelOrder(OrdersCancelled.builder()
.id(orderId)
.cancelTime(LocalDateTime.now())
.cancelReason(ordersCancelReqDTO.getCancelReason())
.cancellerName(currentUser.getName())
.cancellerId(currentUser.getId())
.cancellerType(currentUser.getUserType())
.build());
}
@Override
@Transactional
public void cancelOrder(OrdersCancelled ordersCancelled) {
Long orderId = ordersCancelled.getId();
if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder()
.id(orderId)
.originStatus(OrderStatusEnum.NO_PAY)
.targetStatus(OrderStatusEnum.CANCELLED)
.build())) {
throw new DBException("更新订单表失败");
}
if (!SqlHelper.retBool(baseMapper.insert(ordersCancelled))) {
throw new DBException("更新取消表失败");
}
}
} }

View File

@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.health.mapper.OrdersMapper; import com.jzo2o.health.mapper.OrdersMapper;
import com.jzo2o.health.model.OrderUpdateStatusDTO; import com.jzo2o.health.model.OrderUpdateStatusDTO;
import com.jzo2o.health.model.domain.Orders; import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.service.IOrdersCommonService; import com.jzo2o.health.service.IOrderCommonService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Service;
* @since 2023-08-02 * @since 2023-08-02
*/ */
@Service @Service
public class OrdersCommonServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersCommonService { public class OrderCommonServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrderCommonService {
@Override @Override
public Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) { public Boolean updateStatus(OrderUpdateStatusDTO orderUpdateStatusReqDTO) {
return lambdaUpdate() return lambdaUpdate()

View File

@@ -31,7 +31,7 @@ import com.jzo2o.health.model.dto.response.PlaceOrderResDTO;
import com.jzo2o.health.properties.TradeProperties; import com.jzo2o.health.properties.TradeProperties;
import com.jzo2o.health.service.IMemberService; import com.jzo2o.health.service.IMemberService;
import com.jzo2o.health.service.IOrderCreateService; import com.jzo2o.health.service.IOrderCreateService;
import com.jzo2o.health.service.IOrdersCommonService; import com.jzo2o.health.service.IOrderCommonService;
import com.jzo2o.health.service.ISetmealService; import com.jzo2o.health.service.ISetmealService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -53,7 +53,7 @@ public class OrderCreateServiceImpl extends ServiceImpl<OrdersMapper, Orders> im
@Resource @Resource
private ISetmealService setmealService; private ISetmealService setmealService;
@Resource @Resource
private IOrdersCommonService ordersCommonService; private IOrderCommonService ordersCommonService;
@Resource @Resource
private TradingApi tradingApi; private TradingApi tradingApi;
@Resource @Resource

View File

@@ -2,6 +2,7 @@ package com.jzo2o.health.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.common.constants.UserType;
import com.jzo2o.common.expcetions.ForbiddenOperationException; import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.PageResult; import com.jzo2o.common.model.PageResult;
import com.jzo2o.common.utils.BeanUtils; import com.jzo2o.common.utils.BeanUtils;
@@ -15,6 +16,7 @@ import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.model.domain.OrdersCancelled; import com.jzo2o.health.model.domain.OrdersCancelled;
import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO; import com.jzo2o.health.model.dto.request.OrdersPageQueryReqDTO;
import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO; import com.jzo2o.health.model.dto.response.AdminOrdersDetailResDTO;
import com.jzo2o.health.model.dto.response.OrdersDetailResDTO;
import com.jzo2o.health.model.dto.response.OrdersResDTO; import com.jzo2o.health.model.dto.response.OrdersResDTO;
import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCancelService;
import com.jzo2o.health.service.IOrderManagerService; import com.jzo2o.health.service.IOrderManagerService;
@@ -22,6 +24,7 @@ import com.jzo2o.mysql.utils.PageUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -126,4 +129,37 @@ public class OrderManagerServiceImpl extends ServiceImpl<OrdersMapper, Orders> i
return adminOrdersDetailResDTO; return adminOrdersDetailResDTO;
} }
@Override
public OrdersDetailResDTO getOrderById(Long id) {
Orders orders = baseMapper.selectById(id);
if (ObjectUtils.isEmpty(orders)) {
return new OrdersDetailResDTO();
}
OrdersDetailResDTO ordersDetailResDTO = BeanUtils.toBean(orders, OrdersDetailResDTO.class);
// 订单超时则取消
if (orders.getOrderStatus() == OrderStatusEnum.NO_PAY
&& orders.getPayStatus() == OrderPayStatusEnum.NO_PAY
&& orders.getCreateTime().isBefore(LocalDateTime.now().minusMinutes(15))) {
orderCancelService.cancelOrder(OrdersCancelled.builder()
.id(id)
.cancelTime(LocalDateTime.now())
.cancelReason("订单超时自动取消")
.cancellerType(UserType.SYSTEM)
.build());
ordersDetailResDTO.setOrderStatus(OrderStatusEnum.CANCELLED);
}
if (orders.getOrderStatus() == OrderStatusEnum.CANCELLED
|| orders.getOrderStatus() == OrderStatusEnum.CLOSED) {
OrdersCancelled cancelInfo = orderCancelService.getById(id);
ordersDetailResDTO.setCancelReason(cancelInfo.getCancelReason());
ordersDetailResDTO.setCancelTime(cancelInfo.getCancelTime());
}
return ordersDetailResDTO;
}
} }

View File

@@ -0,0 +1,141 @@
package com.jzo2o.health.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.RefundStatusEnum;
import com.jzo2o.common.expcetions.DBException;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.expcetions.ServerErrorException;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.health.enums.OrderPayStatusEnum;
import com.jzo2o.health.enums.OrderStatusEnum;
import com.jzo2o.health.mapper.OrdersRefundMapper;
import com.jzo2o.health.model.OrderUpdateStatusDTO;
import com.jzo2o.health.model.UserThreadLocal;
import com.jzo2o.health.model.domain.Orders;
import com.jzo2o.health.model.domain.OrdersCancelled;
import com.jzo2o.health.model.domain.OrdersRefund;
import com.jzo2o.health.model.dto.request.OrdersCancelReqDTO;
import com.jzo2o.health.service.IOrderCancelService;
import com.jzo2o.health.service.IOrderCommonService;
import com.jzo2o.health.service.IOrderRefundService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
* 订单退款相关业务层实现
* @author JIAN
*/
@Service
public class OrderRefundServiceImpl extends ServiceImpl<OrdersRefundMapper, OrdersRefund> implements IOrderRefundService {
@Resource
private IOrderCommonService orderCommonService;
@Resource
private IOrderCancelService orderCancelService;
@Resource
private TransactionTemplate transactionTemplate;
@Resource
private RefundRecordApi refundRecordApi;
@Override
@Transactional
public void refundOrder(OrdersCancelReqDTO ordersCancelReqDTO) {
CurrentUserInfo currentUser = UserThreadLocal.currentUser();
if (ObjectUtils.isEmpty(currentUser) || ObjectUtils.isEmpty(currentUser.getId())) {
throw new ForbiddenOperationException("无法获取用户信息无法取消");
}
Long orderId = ordersCancelReqDTO.getId();
Orders orders = orderCommonService.getById(orderId);
if (ObjectUtils.isEmpty(orders)) {
throw new ForbiddenOperationException("订单不存在无法取消");
}
if (orders.getOrderStatus() != OrderStatusEnum.WAITING_CHECKUP || orders.getPayStatus() != OrderPayStatusEnum.PAY_SUCCESS) {
throw new ForbiddenOperationException("订单状态错误无法取消");
}
if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder()
.id(orderId)
.originStatus(OrderStatusEnum.WAITING_CHECKUP)
.targetStatus(OrderStatusEnum.CLOSED)
.payStatus(OrderPayStatusEnum.REFUNDING)
.build())) {
throw new DBException("更新订单表失败");
}
if (!orderCancelService.save(OrdersCancelled.builder()
.id(orderId)
.cancelTime(LocalDateTime.now())
.cancelReason(ordersCancelReqDTO.getCancelReason())
.cancellerName(currentUser.getName())
.cancellerId(currentUser.getId())
.cancellerType(currentUser.getUserType())
.build())) {
throw new DBException("更新取消表失败");
}
OrdersRefund ordersRefund = OrdersRefund.builder()
.id(orderId)
.tradingOrderNo(orders.getTradingOrderNo())
.realPayAmount(/*orders.getSetmealPrice()*/ new BigDecimal("0.01"))
.build();
if (!SqlHelper.retBool(baseMapper.insert(ordersRefund))) {
throw new DBException("更新退款表失败");
}
new Thread(() -> this.refundOrder(ordersRefund)).start();
}
@Override
public void refundOrder(OrdersRefund ordersRefund) {
ExecutionResultResDTO executionResultResDTO = refundRecordApi.refundTrading(ordersRefund.getTradingOrderNo(), ordersRefund.getRealPayAmount());
if (ObjectUtils.isEmpty(executionResultResDTO)) {
throw new ServerErrorException("退款接口调用失败请重试");
}
Integer refundStatus = executionResultResDTO.getRefundStatus();
OrderPayStatusEnum payStatus;
if (RefundStatusEnum.SUCCESS.getCode().equals(refundStatus)) {
payStatus = OrderPayStatusEnum.REFUND_SUCCESS;
} else if (RefundStatusEnum.FAIL.getCode().equals(refundStatus)) {
payStatus = OrderPayStatusEnum.REFUND_FAIL;
} else {
return;
}
transactionTemplate.executeWithoutResult(status -> {
if (!orderCommonService.updateStatus(OrderUpdateStatusDTO.builder()
.id(ordersRefund.getId())
.targetStatus(OrderStatusEnum.CLOSED)
.refundNo(executionResultResDTO.getRefundNo())
.refundId(executionResultResDTO.getRefundId())
.payStatus(payStatus)
.build())) {
throw new DBException("更新订单表失败");
}
if (!SqlHelper.retBool(baseMapper.deleteById(ordersRefund.getId()))) {
throw new DBException("更新退款表失败");
}
});
}
@Override
@SuppressWarnings("unchecked")
public List<OrdersRefund> getLatestRefundInfo(Integer count) {
return lambdaQuery()
.orderByDesc(OrdersRefund::getCreateTime)
.last("LIMIT " + count)
.list();
}
}