套餐相关
This commit is contained in:
parent
32daf27287
commit
054375ebc0
|
@ -12,13 +12,11 @@ import lombok.Getter;
|
|||
@AllArgsConstructor
|
||||
public enum LogBizType {
|
||||
|
||||
UNKNOWN("0", "未知"),
|
||||
PRICE("1", "单价"),
|
||||
REPORT("2", "报表"),
|
||||
PROD_ORDER("3", "生产订单" ),
|
||||
MATERIAL("4", "物料"),
|
||||
UNKNOWN("UNKNOWN", "未知"),
|
||||
ORDER("ORDER", "订单"),
|
||||
UNIT("5", "单位"),
|
||||
SHIFT("6", "调班");
|
||||
SHIFT("6", "调班"),
|
||||
SUIT("SUIT", "套餐");
|
||||
|
||||
private final String type;
|
||||
private final String msg;
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package com.ruoyi.bst.bonus.service;
|
||||
|
||||
public interface BonusConverter {
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.ruoyi.bst.bonus.service.impl;
|
||||
|
||||
import com.ruoyi.bst.bonus.service.BonusConverter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class BonusConverterImpl implements BonusConverter {
|
||||
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@ import com.ruoyi.bst.bonus.domain.enums.BonusArrivalType;
|
|||
import com.ruoyi.bst.bonus.domain.enums.BonusBstType;
|
||||
import com.ruoyi.bst.bonus.domain.enums.BonusStatus;
|
||||
import com.ruoyi.bst.bonus.mapper.BonusMapper;
|
||||
import com.ruoyi.bst.bonus.service.BonusConverter;
|
||||
import com.ruoyi.bst.bonus.service.BonusService;
|
||||
import com.ruoyi.bst.bonus.utils.BonusUtil;
|
||||
import com.ruoyi.bst.bonusRefund.domain.BonusRefund;
|
||||
|
@ -27,7 +26,6 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -62,8 +60,6 @@ public class BonusServiceImpl implements BonusService
|
|||
@Autowired
|
||||
private BonusRefundConverter bonusRefundConverter;
|
||||
|
||||
@Autowired
|
||||
private BonusConverter bonusConverter;
|
||||
|
||||
/**
|
||||
* 查询分成明细
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.ruoyi.bst.order.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
@ -78,6 +79,6 @@ public class Order extends BaseEntity
|
|||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "支付超时时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("支付超时时间")
|
||||
private Date payExpireTime;
|
||||
private LocalDateTime payExpireTime;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
package com.ruoyi.bst.order.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OrderQuery extends OrderVO{
|
||||
|
||||
@ApiModelProperty("订单id列表")
|
||||
private List<Long> orderIds;
|
||||
|
||||
@ApiModelProperty("精准订单编号")
|
||||
private String eqNo;
|
||||
|
||||
@ApiModelProperty("订单状态列表")
|
||||
private List<String> statusList;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
package com.ruoyi.bst.order.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class OrderVO extends Order{
|
||||
|
||||
// 支付
|
||||
@ApiModelProperty("支付单号")
|
||||
private String payNo;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.ruoyi.bst.order.domain.bo;
|
||||
|
||||
import com.ruoyi.bst.app.domain.AppVO;
|
||||
|
||||
import com.ruoyi.bst.channel.domain.ChannelVO;
|
||||
import com.ruoyi.bst.device.domain.DeviceVO;
|
||||
import com.ruoyi.bst.model.domain.ModelVO;
|
||||
import com.ruoyi.bst.order.domain.Order;
|
||||
import com.ruoyi.bst.order.domain.dto.OrderCreateDTO;
|
||||
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
|
||||
import com.ruoyi.bst.pay.domain.vo.DoPayVO;
|
||||
import com.ruoyi.bst.suit.domain.SuitVO;
|
||||
import com.ruoyi.bst.userApp.domain.UserAppVO;
|
||||
import com.ruoyi.common.core.domain.vo.UserVO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OrderCreateBO {
|
||||
|
||||
// 原始参数
|
||||
private OrderCreateDTO dto;
|
||||
|
||||
// 套餐
|
||||
private SuitVO suit;
|
||||
|
||||
// 下单用户
|
||||
private UserVO user;
|
||||
|
||||
// 计算的价格信息
|
||||
private OrderPrePriceVO prePrice;
|
||||
|
||||
// 渠道
|
||||
private ChannelVO channel;
|
||||
|
||||
// APP信息
|
||||
private AppVO app;
|
||||
|
||||
// 用户APP绑定信息
|
||||
private UserAppVO userApp;
|
||||
|
||||
// 生成的订单
|
||||
private Order order;
|
||||
|
||||
// 调起支付的返回值
|
||||
private DoPayVO doPayVO;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.ruoyi.bst.order.domain.dto;
|
||||
|
||||
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
|
||||
import com.ruoyi.common.core.interfaces.LogBizParam;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class OrderCreateDTO implements LogBizParam {
|
||||
|
||||
@ApiModelProperty("下单用户ID")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty("套餐ID")
|
||||
@NotNull(message = "套餐ID不能为空")
|
||||
private Long suitId;
|
||||
|
||||
@ApiModelProperty("APP ID")
|
||||
@NotNull(message = "APP ID不能为空")
|
||||
private Long appId;
|
||||
|
||||
@ApiModelProperty("支付渠道ID")
|
||||
@NotNull(message = "支付渠道ID不能为空")
|
||||
private Long channelId;
|
||||
|
||||
@ApiModelProperty("价格信息")
|
||||
private OrderPrePriceVO price;
|
||||
|
||||
@Override
|
||||
public Object logBizId() {
|
||||
return suitId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.ruoyi.bst.order.domain.enums;
|
||||
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum OrderStatus {
|
||||
|
||||
WAIT_PAY("WAIT_PAY", "待支付"),
|
||||
PROCESSING("PROCESSING", "进行中"),
|
||||
FINISHED("FINISHED", "已结束"),
|
||||
CANCELED("CANCELED", "已取消"),
|
||||
WAIT_VERIFY("WAIT_VERIFY", "待审核"),
|
||||
REJECTED("REJECTED", "已驳回"),
|
||||
REFUNDED("REFUNDED", "已退款");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
|
||||
// 允许支付的订单状态
|
||||
public static List<String> canPay() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, WAIT_PAY);
|
||||
}
|
||||
|
||||
// 正在使用中的订单状态
|
||||
public static List<String> inUse() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, PROCESSING);
|
||||
}
|
||||
|
||||
// 可以支付成功的订单状态
|
||||
public static List<String> canPaySuccess() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, WAIT_PAY);
|
||||
}
|
||||
|
||||
// 可以结束的订单状态
|
||||
public static List<String> canEnd() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, PROCESSING);
|
||||
}
|
||||
|
||||
// 可以退款的订单状态
|
||||
public static List<String> canRefund() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, FINISHED, REFUNDED, REJECTED, WAIT_VERIFY);
|
||||
}
|
||||
|
||||
// 未支付的订单状态
|
||||
public static List<String> unPayList() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, WAIT_PAY);
|
||||
}
|
||||
|
||||
// 可以取消支付的订单状态
|
||||
public static List<String> canCancelPay() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, WAIT_PAY);
|
||||
}
|
||||
|
||||
// 可以审核的订单状态
|
||||
public static List<String> canVerify() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, WAIT_VERIFY);
|
||||
}
|
||||
|
||||
// 有效的订单状态:已支付的订单
|
||||
public static List<String> valid() {
|
||||
return CollectionUtils.map(OrderStatus::getCode, PROCESSING, FINISHED, WAIT_VERIFY, REJECTED, REFUNDED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.ruoyi.bst.order.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class OrderPrePriceVO {
|
||||
|
||||
@ApiModelProperty("支付金额")
|
||||
private BigDecimal payAmount;
|
||||
|
||||
}
|
|
@ -71,4 +71,21 @@ public interface OrderMapper
|
|||
* @return 结果
|
||||
*/
|
||||
public int deleteOrderByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 根据查询条件查询订单ID列表
|
||||
* @param query 查询条件
|
||||
* @return 订单ID列表
|
||||
*/
|
||||
List<Long> selectIdByQuery(@Param("query") OrderQuery query);
|
||||
|
||||
|
||||
/**
|
||||
* 根据查询条件更新订单
|
||||
* @param data 更新数据
|
||||
* @param query 查询条件
|
||||
* @return 结果
|
||||
*/
|
||||
int updateByQuery(@Param("data") Order data, @Param("query") OrderQuery query);
|
||||
|
||||
}
|
||||
|
|
|
@ -25,23 +25,29 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
|
||||
<sql id="selectOrderVo">
|
||||
select
|
||||
id,
|
||||
order_no,
|
||||
store_id,
|
||||
store_name,
|
||||
user_id,
|
||||
pay_id,
|
||||
pay_amount,
|
||||
mark,
|
||||
status,
|
||||
create_time,
|
||||
suit_id,
|
||||
suit_name,
|
||||
suit_num,
|
||||
suit_amount,
|
||||
cancel_remark,
|
||||
pay_expire_time
|
||||
from bst_order
|
||||
bo.id,
|
||||
bo.order_no,
|
||||
bo.store_id,
|
||||
bo.store_name,
|
||||
bo.user_id,
|
||||
bo.pay_id,
|
||||
bo.pay_amount,
|
||||
bo.mark,
|
||||
bo.status,
|
||||
bo.create_time,
|
||||
bo.suit_id,
|
||||
bo.suit_name,
|
||||
bo.suit_num,
|
||||
bo.suit_amount,
|
||||
bo.cancel_remark,
|
||||
bo.pay_expire_time
|
||||
from <include refid="searchTables"></include>
|
||||
</sql>
|
||||
|
||||
<sql id="searchTables">
|
||||
bst_order bo
|
||||
left join sys_user su on bo.user_id = su.user_id
|
||||
left join bst_pay bp on bo.pay_id = bp.id
|
||||
</sql>
|
||||
|
||||
<sql id="searchCondition">
|
||||
|
@ -73,6 +79,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<include refid="selectOrderVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
<!-- selectIdByQuery -->
|
||||
|
||||
<select id="selectIdByQuery" resultType="Long">
|
||||
select bo.id
|
||||
from <include refid="searchTables"/>
|
||||
<where>
|
||||
<include refid="searchCondition"/>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
<insert id="insertOrder" parameterType="Order" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into bst_order
|
||||
|
@ -336,6 +352,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
where id = #{data.id}
|
||||
</update>
|
||||
|
||||
<!-- updateByQuery -->
|
||||
<update id="updateByQuery">
|
||||
update bst_order bo
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<include refid="updateColumns"/>
|
||||
</trim>
|
||||
<where>
|
||||
<include refid="searchCondition"/>
|
||||
</where>
|
||||
</update>
|
||||
|
||||
<sql id="updateColumns">
|
||||
<if test="data.orderNo != null and data.orderNo != ''">order_no = #{data.orderNo},</if>
|
||||
<if test="data.storeId != null">store_id = #{data.storeId},</if>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.ruoyi.bst.order.service;
|
||||
|
||||
import com.ruoyi.bst.order.domain.Order;
|
||||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
import com.ruoyi.bst.order.domain.dto.*;
|
||||
|
||||
public interface OrderConverter {
|
||||
|
||||
|
||||
/**
|
||||
* 订单创建,将DTO转换为BO
|
||||
*/
|
||||
OrderCreateBO toCreateBO(OrderCreateDTO dto);
|
||||
|
||||
}
|
|
@ -4,6 +4,8 @@ import java.util.List;
|
|||
import com.ruoyi.bst.order.domain.Order;
|
||||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.OrderQuery;
|
||||
import com.ruoyi.bst.order.domain.dto.OrderCreateDTO;
|
||||
import com.ruoyi.bst.pay.domain.vo.DoPayVO;
|
||||
|
||||
/**
|
||||
* 订单列表Service接口
|
||||
|
@ -60,4 +62,50 @@ public interface OrderService
|
|||
* @return 结果
|
||||
*/
|
||||
public int deleteOrderById(Long id);
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
* @param dto 创建订单DTO
|
||||
* @return 订单
|
||||
*/
|
||||
public DoPayVO createOrder(OrderCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
* @param no 订单编号
|
||||
* @param scope 是否数据隔离
|
||||
* @return 订单
|
||||
*/
|
||||
public OrderVO selectOrderByNo(String no, boolean scope);
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
* @param no 订单编号
|
||||
* @return 订单
|
||||
*/
|
||||
default OrderVO selectOrderByNo(String no) {
|
||||
return this.selectOrderByNo(no, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询单个订单
|
||||
* @param query 查询条件
|
||||
* @return 订单
|
||||
*/
|
||||
public OrderVO selectOne(OrderQuery query);
|
||||
|
||||
/**
|
||||
* 取消过期订单
|
||||
* @param order 订单
|
||||
*/
|
||||
public void cancelWhenExpired(Order order);
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* @param id 订单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int cancelOrder(Long id, String remark);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.ruoyi.bst.order.service;
|
||||
|
||||
import com.ruoyi.bst.device.domain.DeviceVO;
|
||||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
|
||||
public interface OrderValidator {
|
||||
|
||||
/**
|
||||
* 校验订单BO
|
||||
* @param bo 订单BO
|
||||
*/
|
||||
void validate(OrderCreateBO bo);
|
||||
|
||||
/**
|
||||
* 校验用户是否可以支付指定订单
|
||||
* @param order 订单
|
||||
* @param userId 用户ID
|
||||
* @return 是否可以支付
|
||||
*/
|
||||
boolean canPay(OrderVO order, Long userId);
|
||||
|
||||
/**
|
||||
* 校验普通用户是否可以结束指定订单
|
||||
* @param order 订单
|
||||
* @param userId 用户ID
|
||||
* @return 是否可以结束
|
||||
*/
|
||||
boolean canEnd(OrderVO order, Long userId);
|
||||
|
||||
|
||||
/**
|
||||
* 校验用户是否可以操作设备开启
|
||||
* @param order 订单
|
||||
* @param userId 用户ID
|
||||
* @return 是否可以操作设备开启
|
||||
*/
|
||||
boolean canOpenDevice(OrderVO order, Long userId);
|
||||
|
||||
/**
|
||||
* 校验用户是否可以操作设备关闭
|
||||
* @param order 订单
|
||||
* @param userId 用户ID
|
||||
* @return 是否可以操作设备关闭
|
||||
*/
|
||||
boolean canCloseDevice(OrderVO order, Long userId);
|
||||
|
||||
/**
|
||||
* 校验用户是否可以操作指定订单
|
||||
* @param orderId 订单ID
|
||||
* @return 是否可以操作
|
||||
*/
|
||||
boolean canOperate(Long orderId);
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package com.ruoyi.bst.order.service.impl;
|
||||
|
||||
import com.ruoyi.bst.app.domain.AppVO;
|
||||
import com.ruoyi.bst.app.service.AppService;
|
||||
import com.ruoyi.bst.channel.domain.ChannelVO;
|
||||
import com.ruoyi.bst.channel.service.ChannelService;
|
||||
import com.ruoyi.bst.device.service.DeviceIotService;
|
||||
import com.ruoyi.bst.device.service.DeviceService;
|
||||
|
||||
import com.ruoyi.bst.model.service.ModelService;
|
||||
import com.ruoyi.bst.order.domain.Order;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
import com.ruoyi.bst.order.domain.dto.*;
|
||||
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
|
||||
import com.ruoyi.bst.order.service.OrderConverter;
|
||||
import com.ruoyi.bst.order.service.OrderService;
|
||||
import com.ruoyi.bst.order.utils.OrderUtil;
|
||||
import com.ruoyi.bst.suit.domain.SuitVO;
|
||||
import com.ruoyi.bst.suit.service.SuitService;
|
||||
import com.ruoyi.bst.userApp.domain.UserAppVO;
|
||||
import com.ruoyi.bst.userApp.service.UserAppService;
|
||||
import com.ruoyi.common.core.domain.vo.UserVO;
|
||||
|
||||
import com.ruoyi.system.user.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
public class OrderConverterImpl implements OrderConverter{
|
||||
|
||||
@Autowired
|
||||
private SuitService suitService;
|
||||
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private AppService appService;
|
||||
|
||||
@Autowired
|
||||
private UserAppService userAppService;
|
||||
|
||||
@Autowired
|
||||
private DeviceIotService deviceIotService;
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private ModelService modelService;
|
||||
|
||||
|
||||
@Override
|
||||
public OrderCreateBO toCreateBO(OrderCreateDTO dto) {
|
||||
if (dto == null) {
|
||||
return null;
|
||||
}
|
||||
OrderCreateBO bo = new OrderCreateBO();
|
||||
bo.setDto(dto);
|
||||
|
||||
// 套餐
|
||||
SuitVO suit = suitService.selectSuitById(dto.getSuitId());
|
||||
bo.setSuit(suit);
|
||||
|
||||
// 用户
|
||||
UserVO user = userService.selectUserById(dto.getUserId());
|
||||
bo.setUser(user);
|
||||
|
||||
// 查询渠道
|
||||
ChannelVO channel = channelService.selectChannelByChannelId(dto.getChannelId());
|
||||
bo.setChannel(channel);
|
||||
|
||||
// 查询应用
|
||||
AppVO app = appService.selectAppById(dto.getAppId());
|
||||
bo.setApp(app);
|
||||
|
||||
// 价格信息
|
||||
OrderPrePriceVO prePrice = OrderUtil.calcPrePrice(suit);
|
||||
bo.setPrePrice(prePrice);
|
||||
|
||||
|
||||
// 查询用户应用信息
|
||||
if (user != null && app != null) {
|
||||
UserAppVO userApp = userAppService.selectByUserApp(user.getUserId(), app.getId());
|
||||
bo.setUserApp(userApp);
|
||||
}
|
||||
|
||||
// 生成订单
|
||||
Order order = this.generateOrder(bo);
|
||||
bo.setOrder(order);
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
|
||||
// 生成订单
|
||||
private Order generateOrder(OrderCreateBO bo) {
|
||||
if (bo == null) {
|
||||
return null;
|
||||
}
|
||||
Order order = new Order();
|
||||
// 基础信息
|
||||
order.setPayExpireTime(LocalDateTime.now().plusMinutes(3));
|
||||
|
||||
// 用户信息
|
||||
UserVO user = bo.getUser();
|
||||
if (user != null) {
|
||||
order.setUserId(user.getUserId());
|
||||
}
|
||||
|
||||
// 套餐信息
|
||||
SuitVO suit = bo.getSuit();
|
||||
if (suit != null) {
|
||||
order.setStoreId(suit.getStoreId());
|
||||
order.setSuitId(suit.getSuitId());
|
||||
order.setSuitName(suit.getSuitName());
|
||||
order.setPayAmount(suit.getRechargeAmount());
|
||||
order.setSuitNum(suit.getLightingNums());
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,28 @@
|
|||
package com.ruoyi.bst.order.service.impl;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
import com.ruoyi.bst.order.domain.dto.OrderCreateDTO;
|
||||
import com.ruoyi.bst.order.domain.enums.OrderStatus;
|
||||
import com.ruoyi.bst.order.service.OrderConverter;
|
||||
import com.ruoyi.bst.order.service.OrderValidator;
|
||||
import com.ruoyi.bst.pay.domain.Pay;
|
||||
import com.ruoyi.bst.pay.domain.enums.PayBstType;
|
||||
import com.ruoyi.bst.pay.domain.vo.DoPayVO;
|
||||
import com.ruoyi.bst.pay.service.PayConverter;
|
||||
import com.ruoyi.bst.pay.service.PayService;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.ServiceUtil;
|
||||
import com.ruoyi.common.utils.SnowFlakeUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.bst.order.mapper.OrderMapper;
|
||||
|
@ -9,6 +30,7 @@ import com.ruoyi.bst.order.domain.Order;
|
|||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.OrderQuery;
|
||||
import com.ruoyi.bst.order.service.OrderService;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* 订单列表Service业务层处理
|
||||
|
@ -21,7 +43,18 @@ public class OrderServiceImpl implements OrderService
|
|||
{
|
||||
@Autowired
|
||||
private OrderMapper orderMapper;
|
||||
|
||||
@Autowired
|
||||
private TransactionTemplate transactionTemplate;
|
||||
@Autowired
|
||||
private OrderConverter orderConverter;
|
||||
@Autowired
|
||||
private OrderValidator orderValidator;
|
||||
@Autowired
|
||||
private PayConverter payConverter;
|
||||
@Autowired
|
||||
private PayService payService;
|
||||
@Autowired
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
/**
|
||||
* 查询订单列表
|
||||
*
|
||||
|
@ -56,6 +89,7 @@ public class OrderServiceImpl implements OrderService
|
|||
public int insertOrder(Order order)
|
||||
{
|
||||
order.setCreateTime(DateUtils.getNowDate());
|
||||
order.setOrderNo(String.valueOf(SnowFlakeUtil.newId()));
|
||||
return orderMapper.insertOrder(order);
|
||||
}
|
||||
|
||||
|
@ -94,4 +128,125 @@ public class OrderServiceImpl implements OrderService
|
|||
{
|
||||
return orderMapper.deleteOrderById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoPayVO createOrder(OrderCreateDTO dto) {
|
||||
// 转为BO对象
|
||||
OrderCreateBO bo = orderConverter.toCreateBO(dto);
|
||||
// 校验参数
|
||||
orderValidator.validate(bo);
|
||||
|
||||
return transactionTemplate.execute(status -> {
|
||||
|
||||
// 创建订单
|
||||
Order order = bo.getOrder();
|
||||
int rows = this.insertOrder(order);
|
||||
ServiceUtil.assertion(rows != 1, "创建订单失败");
|
||||
|
||||
// 查询订单
|
||||
OrderVO vo = this.selectOrderByNo(order.getOrderNo());
|
||||
ServiceUtil.assertion(vo == null, "查询创建的订单失败");
|
||||
|
||||
// 支付
|
||||
DoPayVO doPayVO = this.pay(bo);
|
||||
ServiceUtil.assertion(doPayVO == null, "支付失败");
|
||||
bo.setDoPayVO(doPayVO);
|
||||
|
||||
// 加入延时队列,超时取消
|
||||
this.cancelWhenExpired(order);
|
||||
return doPayVO;
|
||||
});
|
||||
}
|
||||
|
||||
private DoPayVO pay(OrderCreateBO bo) {
|
||||
|
||||
// 转为支付PO
|
||||
Pay pay = payConverter.toPayPO(bo);
|
||||
ServiceUtil.assertion(pay == null, "转为支付单失败");
|
||||
|
||||
return transactionTemplate.execute(status -> {
|
||||
// 创建并调起支付
|
||||
return payService.createPayBill(pay);
|
||||
});
|
||||
}
|
||||
|
||||
// 加入延时队列,超时取消
|
||||
@Override
|
||||
public void cancelWhenExpired(Order order) {
|
||||
if (order == null || order.getPayExpireTime() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Duration duration = Duration.between(LocalDateTime.now(), order.getPayExpireTime());
|
||||
long delay = duration.getSeconds();
|
||||
if (delay <= 0) {
|
||||
delay = 1;
|
||||
}
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
// 尝试取消订单
|
||||
this.cancelOrder(order.getId(), "订单超时取消");
|
||||
}, delay, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
@Override
|
||||
public int cancelOrder(Long id, String remark) {
|
||||
if (id == null) {
|
||||
return 0;
|
||||
}
|
||||
// 查询订单
|
||||
OrderVO order = this.selectOrderById(id);
|
||||
ServiceUtil.assertion(order == null, "ID为%s的订单不存在", id);
|
||||
ServiceUtil.assertion(!OrderStatus.canCancelPay().contains(order.getStatus()), "ID为%s的订单当前状态不允许取消", id);
|
||||
|
||||
// 刷新支付结果
|
||||
if (order.getPayNo() != null) {
|
||||
payService.refreshPayResult(order.getPayNo());
|
||||
}
|
||||
|
||||
// 查询最新订单状态
|
||||
order = this.selectOrderById(id);
|
||||
ServiceUtil.assertion(order == null, "ID为%s的订单不存在", id);
|
||||
ServiceUtil.assertion(!OrderStatus.canCancelPay().contains(order.getStatus()), "ID为%s的订单当前状态不允许取消", id);
|
||||
|
||||
|
||||
// 取消订单
|
||||
Integer result = transactionTemplate.execute(status -> {
|
||||
// 更新订单状态
|
||||
Order data = new Order();
|
||||
data.setStatus(OrderStatus.CANCELED.getCode());
|
||||
data.setCancelRemark(remark);
|
||||
OrderQuery query = new OrderQuery();
|
||||
query.setId(id);
|
||||
query.setStatusList(OrderStatus.canCancelPay());
|
||||
int rows = orderMapper.updateByQuery(data, query);
|
||||
ServiceUtil.assertion(rows != 1, "ID为%s的订单取消失败,状态已发生变化", id);
|
||||
|
||||
// 取消支付单
|
||||
boolean cancelPay = payService.closeByBstId(PayBstType.ORDER.getType(), id);
|
||||
ServiceUtil.assertion(!cancelPay, "ID为%s的订单取消支付单失败", id);
|
||||
|
||||
return rows;
|
||||
});
|
||||
|
||||
return result == null ? 0 : result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderVO selectOrderByNo(String no, boolean scope) {
|
||||
if (StringUtils.isBlank(no)) {
|
||||
return null;
|
||||
}
|
||||
OrderQuery query = new OrderQuery();
|
||||
query.setEqNo(no);
|
||||
query.setScope(scope);
|
||||
return this.selectOne(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderVO selectOne(OrderQuery query) {
|
||||
PageHelper.startPage(1, 1);
|
||||
List<OrderVO> list = this.selectOrderList(query);
|
||||
return CollectionUtils.firstElement(list);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package com.ruoyi.bst.order.service.impl;
|
||||
|
||||
import com.ruoyi.bst.app.domain.AppVO;
|
||||
|
||||
import com.ruoyi.bst.channel.domain.ChannelVO;
|
||||
|
||||
import com.ruoyi.bst.device.service.DeviceService;
|
||||
|
||||
import com.ruoyi.bst.order.domain.OrderQuery;
|
||||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
|
||||
import com.ruoyi.bst.order.domain.dto.OrderCreateDTO;
|
||||
|
||||
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
|
||||
import com.ruoyi.bst.order.mapper.OrderMapper;
|
||||
import com.ruoyi.bst.order.service.OrderValidator;
|
||||
import com.ruoyi.bst.order.utils.OrderUtil;
|
||||
import com.ruoyi.bst.suit.domain.SuitVO;
|
||||
import com.ruoyi.common.core.domain.vo.UserVO;
|
||||
import com.ruoyi.common.utils.ServiceUtil;
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OrderValidatorImpl implements OrderValidator{
|
||||
|
||||
@Autowired
|
||||
private OrderMapper orderMapper;
|
||||
|
||||
@Override
|
||||
public void validate(OrderCreateBO bo) {
|
||||
ServiceUtil.assertion(bo == null, "参数错误");
|
||||
|
||||
OrderCreateDTO dto = bo.getDto();
|
||||
ServiceUtil.assertion(dto == null, "参数错误");
|
||||
|
||||
// 套餐
|
||||
SuitVO suit = bo.getSuit();
|
||||
ServiceUtil.assertion(suit == null, "ID为%s的套餐不存在", dto.getSuitId());
|
||||
|
||||
// 用户
|
||||
UserVO user = bo.getUser();
|
||||
ServiceUtil.assertion(user == null, "ID为%s的用户不存在", dto.getUserId());
|
||||
|
||||
// 价格
|
||||
OrderPrePriceVO prePrice = bo.getPrePrice();
|
||||
ServiceUtil.assertion(prePrice == null, "价格计算失败");
|
||||
// 是否和前端传输的价格一致
|
||||
boolean priceEquals = OrderUtil.isEquals(prePrice, dto.getPrice());
|
||||
ServiceUtil.assertion(!priceEquals, "当前价格已发生变化,请刷新后重新下单");
|
||||
|
||||
// 应用
|
||||
AppVO app = bo.getApp();
|
||||
ServiceUtil.assertion(app == null, "ID为%s的应用不存在", dto.getAppId());
|
||||
|
||||
// 渠道
|
||||
ChannelVO channel = bo.getChannel();
|
||||
ServiceUtil.assertion(channel == null, "ID为%s的渠道不存在", dto.getChannelId());
|
||||
ServiceUtil.assertion(channel.getEnabled() == null || !channel.getEnabled(), "ID为%s的渠道暂不可用", channel.getChannelId());
|
||||
ServiceUtil.assertion(channel.getAppIds() == null || !channel.getAppIds().contains(app.getId()), "ID为%s的渠道不支持ID为%s的应用", channel.getChannelId(), app.getId());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(OrderVO order, Long userId) {
|
||||
return isUser(order, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEnd(OrderVO order, Long userId) {
|
||||
return isUser(order, userId);
|
||||
}
|
||||
|
||||
// 是否是下单用户
|
||||
private boolean isUser(OrderVO order, Long userId) {
|
||||
return order != null && userId != null && Objects.equals(order.getUserId(), userId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canOpenDevice(OrderVO order, Long userId) {
|
||||
return isUser(order, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCloseDevice(OrderVO order, Long userId) {
|
||||
return isUser(order, userId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canOperate(Long orderId) {
|
||||
return hasPermission(Collections.singletonList(orderId));
|
||||
}
|
||||
|
||||
private boolean hasPermission(List<Long> orderIds) {
|
||||
if (CollectionUtils.isEmptyElement(orderIds)) {
|
||||
return true;
|
||||
}
|
||||
OrderQuery query = new OrderQuery();
|
||||
query.setScope(true);
|
||||
query.setOrderIds(orderIds);
|
||||
List<Long> list = orderMapper.selectIdByQuery(query);
|
||||
return new HashSet<>(list).containsAll(orderIds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.ruoyi.bst.order.utils;
|
||||
|
||||
import com.ruoyi.bst.device.domain.DeviceQuery;
|
||||
import com.ruoyi.bst.device.domain.DeviceVO;
|
||||
import com.ruoyi.bst.device.domain.enums.DeviceStatus;
|
||||
import com.ruoyi.bst.order.domain.OrderVO;
|
||||
import com.ruoyi.bst.order.domain.vo.OrderPrePriceVO;
|
||||
import com.ruoyi.bst.suit.domain.SuitVO;
|
||||
import com.ruoyi.common.utils.MathUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public class OrderUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 判断两个价格是否一致
|
||||
* @param a 价格A
|
||||
* @param b 价格B
|
||||
* @return 是否一致
|
||||
*/
|
||||
public static boolean isEquals(OrderPrePriceVO a, OrderPrePriceVO b) {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
return MathUtils.equals(a.getPayAmount(), b.getPayAmount());
|
||||
}
|
||||
|
||||
public static OrderPrePriceVO calcPrePrice(SuitVO suit) {
|
||||
if (suit == null) {
|
||||
return null;
|
||||
}
|
||||
OrderPrePriceVO vo = new OrderPrePriceVO();
|
||||
vo.setPayAmount(suit.getRechargeAmount());
|
||||
return vo;
|
||||
}
|
||||
//
|
||||
// public static BigDecimal calcCanRefundAmount(OrderVO order) {
|
||||
// if (order == null) {
|
||||
// return BigDecimal.ZERO;
|
||||
// }
|
||||
// return MathUtils.subtractDecimal(order.getPayAmount(), order.getPayRefunding(), order.getPayRefunded());
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,7 +1,15 @@
|
|||
package com.ruoyi.bst.pay.service;
|
||||
|
||||
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
import com.ruoyi.bst.pay.domain.Pay;
|
||||
|
||||
public interface PayConverter {
|
||||
|
||||
/**
|
||||
* 将订单支付BO转换为支付PO
|
||||
*/
|
||||
Pay toPayPO(OrderCreateBO bo);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.ruoyi.bst.pay.service.impl;
|
|||
|
||||
import com.ruoyi.bst.app.domain.AppVO;
|
||||
import com.ruoyi.bst.channel.domain.ChannelVO;
|
||||
import com.ruoyi.bst.order.domain.Order;
|
||||
import com.ruoyi.bst.order.domain.bo.OrderCreateBO;
|
||||
import com.ruoyi.bst.pay.domain.Pay;
|
||||
import com.ruoyi.bst.pay.domain.enums.PayBstType;
|
||||
import com.ruoyi.bst.pay.domain.enums.PayStatus;
|
||||
|
@ -17,5 +19,45 @@ import java.time.LocalDateTime;
|
|||
@Service
|
||||
public class PayConverterImpl implements PayConverter {
|
||||
|
||||
@Override
|
||||
public Pay toPayPO(OrderCreateBO bo) {
|
||||
if (bo == null) {
|
||||
return null;
|
||||
}
|
||||
Order order = bo.getOrder();
|
||||
UserVO user = bo.getUser();
|
||||
ChannelVO channel = bo.getChannel();
|
||||
UserAppVO userApp = bo.getUserApp();
|
||||
AppVO app = bo.getApp();
|
||||
if (order == null || user == null || channel == null || userApp == null || app == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Pay pay = new Pay();
|
||||
// 基础信息
|
||||
pay.setStatus(PayStatus.WAIT_PAY.getStatus());
|
||||
pay.setExpireTime(LocalDateTime.now().plusMinutes(10));
|
||||
|
||||
// 订单信息
|
||||
pay.setBstType(PayBstType.ORDER.getType());
|
||||
pay.setBstId(order.getId());
|
||||
pay.setAmount(order.getPayAmount());
|
||||
|
||||
// 用户信息
|
||||
pay.setAccount(userApp.getOpenId());
|
||||
pay.setIp(IpUtils.getIpAddr());
|
||||
|
||||
// 应用信息
|
||||
pay.setAppId(app.getId());
|
||||
pay.setAppName(app.getName());
|
||||
|
||||
// 渠道信息
|
||||
pay.setChannelId(channel.getChannelId());
|
||||
pay.setChannelName(channel.getName());
|
||||
|
||||
// 渠道成本(放最后)
|
||||
pay.setChannelCost(MathUtils.mulDecimal(channel.getCostRate(), pay.getAmount()));
|
||||
return pay;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,33 @@
|
|||
package com.ruoyi.web.app;
|
||||
|
||||
import com.ruoyi.bst.order.domain.dto.OrderCreateDTO;
|
||||
import com.ruoyi.bst.order.service.OrderService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.enums.LogBizType;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/app/order")
|
||||
public class AppOrderController {
|
||||
public class AppOrderController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@ApiOperation("下单并支付")
|
||||
@PostMapping
|
||||
@Log(title = "下单并支付", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.SUIT)
|
||||
public AjaxResult createOrder(@RequestBody @Validated OrderCreateDTO dto) {
|
||||
dto.setUserId(getUserId());
|
||||
return success(orderService.createOrder(dto));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class OrderController extends BaseController
|
|||
{
|
||||
startPage();
|
||||
startOrderBy();
|
||||
query.setScope(true);
|
||||
List<OrderVO> list = orderService.selectOrderList(query);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user