|
@@ -1,10 +1,45 @@
|
|
|
package com.qs.mp.user.service.impl;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.qs.mp.admin.domain.Ticket;
|
|
|
+import com.qs.mp.admin.domain.TicketBox;
|
|
|
+import com.qs.mp.admin.service.ITicketBoxService;
|
|
|
+import com.qs.mp.admin.service.ITicketService;
|
|
|
+import com.qs.mp.channel.domain.ChannelOrder;
|
|
|
+import com.qs.mp.channel.domain.ChannelUserRel;
|
|
|
+import com.qs.mp.channel.service.IChannelUserRelService;
|
|
|
+import com.qs.mp.common.enums.ChannelOrderStatusEnum;
|
|
|
+import com.qs.mp.common.enums.TicketBoxStatusEnum;
|
|
|
+import com.qs.mp.common.enums.TicketStatusEnum;
|
|
|
+import com.qs.mp.common.enums.TicketTypeEnum;
|
|
|
+import com.qs.mp.common.enums.UserCouponStatusEnum;
|
|
|
+import com.qs.mp.common.enums.UserTicketOrderStatusEnum;
|
|
|
+import com.qs.mp.common.exception.ServiceException;
|
|
|
+import com.qs.mp.common.utils.LogUtil;
|
|
|
+import com.qs.mp.common.utils.StringUtils;
|
|
|
+import com.qs.mp.pay.domain.PayOrder;
|
|
|
+import com.qs.mp.system.service.id.BizIdGenerator;
|
|
|
+import com.qs.mp.user.domain.UserCoupon;
|
|
|
import com.qs.mp.user.domain.UserTicketOrder;
|
|
|
+import com.qs.mp.user.domain.UserTicketOrderItem;
|
|
|
+import com.qs.mp.user.domain.vo.TicketOrderSettleVO;
|
|
|
+import com.qs.mp.user.domain.vo.UserCouponVO;
|
|
|
import com.qs.mp.user.mapper.UserTicketOrderMapper;
|
|
|
+import com.qs.mp.user.service.IUserCouponService;
|
|
|
+import com.qs.mp.user.service.IUserTicketOrderItemService;
|
|
|
import com.qs.mp.user.service.IUserTicketOrderService;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
/**
|
|
|
* <p>
|
|
@@ -17,4 +52,197 @@ import org.springframework.stereotype.Service;
|
|
|
@Service
|
|
|
public class UserTicketOrderServiceImpl extends ServiceImpl<UserTicketOrderMapper, UserTicketOrder> implements IUserTicketOrderService {
|
|
|
|
|
|
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ITicketBoxService ticketBoxService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IUserCouponService userCouponService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IChannelUserRelService channelUserRelService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IUserTicketOrderItemService userTicketOrderItemService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ITicketService ticketService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private BizIdGenerator bizIdGenerator;
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public String submitOrder(Long userId, TicketOrderSettleVO orderSettleVO) {
|
|
|
+ if (StringUtils.isNotBlank(orderSettleVO.getBoxId())){
|
|
|
+ return createOnlineOrder(userId, orderSettleVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 线下票不需锁库存,待付款成功后再更新票组销量
|
|
|
+ return createOfflineOrder(userId, orderSettleVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String createOnlineOrder(Long userId, TicketOrderSettleVO orderSettleVO) {
|
|
|
+ // 线上票更新票组销量,防止超卖
|
|
|
+ TicketBox ticketBox = ticketBoxService.getById(orderSettleVO.getBoxId());
|
|
|
+ if (ticketBox.getStatus() == TicketBoxStatusEnum.PUT_OFF || ticketBox.getSaleQty() + orderSettleVO.getOrderNum() > ticketBox.getQuantity()) {
|
|
|
+ LogUtil.error(logger, "库存不足,boxId:{0},qty:{1},saleQty:{2},orderNum:{3}", new Object[]{ticketBox.getBoxId(), ticketBox.getQuantity(), ticketBox.getSaleQty(), orderSettleVO.getOrderNum()});
|
|
|
+ throw new ServiceException("库存不足");
|
|
|
+ }
|
|
|
+ boolean rst = ticketBoxService.update(new LambdaUpdateWrapper<TicketBox>().set(TicketBox::getSaleQty, ticketBox.getSaleQty() + orderSettleVO.getOrderNum())
|
|
|
+ .set(ticketBox.getSaleQty() + orderSettleVO.getOrderNum() == ticketBox.getQuantity(),TicketBox::getStatus, TicketBoxStatusEnum.PUT_OFF)
|
|
|
+ .eq(TicketBox::getBoxId, ticketBox.getBoxId()).eq(TicketBox::getSaleQty, ticketBox.getSaleQty()));
|
|
|
+ if (!rst) {
|
|
|
+ LogUtil.error(logger, "盲票购买订单创建时,更新盲票销量失败。boxId:{0}, saleQty:{1}", new Object[]{ticketBox.getBoxId(), ticketBox.getSaleQty()});
|
|
|
+ throw new ServiceException("盲票购买订单创建时,更新盲票销量失败");
|
|
|
+ }
|
|
|
+ // 核销优惠券
|
|
|
+ String couponIds = verifyUserCoupon(orderSettleVO.getCouponList());
|
|
|
+
|
|
|
+ // 创建订单
|
|
|
+ UserTicketOrder userTicketOrder = new UserTicketOrder();
|
|
|
+ userTicketOrder.setOrderId(bizIdGenerator.newId());
|
|
|
+ userTicketOrder.setUserId(userId);
|
|
|
+ userTicketOrder.setTitle(orderSettleVO.getTitle());
|
|
|
+ userTicketOrder.setBoxId(orderSettleVO.getBoxId());
|
|
|
+ userTicketOrder.setOrderAmt(orderSettleVO.getOrderAmt());
|
|
|
+ userTicketOrder.setDiscountAmt(orderSettleVO.getDiscountAmt());
|
|
|
+ userTicketOrder.setPayAmt(orderSettleVO.getPayAmt());
|
|
|
+ userTicketOrder.setTicketNum(orderSettleVO.getOrderNum());
|
|
|
+ userTicketOrder.setMemo("");
|
|
|
+ userTicketOrder.setResource(TicketTypeEnum.ONLINE);
|
|
|
+ userTicketOrder.setCouponInfo(couponIds);
|
|
|
+ userTicketOrder.setStatus(UserTicketOrderStatusEnum.NOT_PAY);
|
|
|
+ save(userTicketOrder);
|
|
|
+
|
|
|
+ // 查询用户的所属经销商,线上票直接查询
|
|
|
+ ChannelUserRel channelUserRel = channelUserRelService.getOne(new LambdaQueryWrapper<ChannelUserRel>()
|
|
|
+ .eq(ChannelUserRel::getUserId, userId));
|
|
|
+ for (int i = 0; i < orderSettleVO.getOrderNum(); i++) {
|
|
|
+ UserTicketOrderItem orderItem = new UserTicketOrderItem();
|
|
|
+ orderItem.setItemId(bizIdGenerator.newId());
|
|
|
+ orderItem.setOrderId(userTicketOrder.getOrderId());
|
|
|
+ orderItem.setUserId(userId);
|
|
|
+ orderItem.setBoxId(ticketBox.getBoxId());
|
|
|
+ orderItem.setTicketId(null); // 付款成功后再分配具体盲票
|
|
|
+ orderItem.setChannelId(null == channelUserRel ? null : channelUserRel.getChannelId());
|
|
|
+ userTicketOrderItemService.save(orderItem);
|
|
|
+ }
|
|
|
+ return userTicketOrder.getOrderId();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String createOfflineOrder(Long userId, TicketOrderSettleVO orderSettleVO) {
|
|
|
+ Ticket ticket = ticketService.getById(orderSettleVO.getTicketId());
|
|
|
+ if (ticket.getStatus() != TicketStatusEnum.NOT_PAY) {
|
|
|
+ LogUtil.error(logger, "盲票已付款,ticketId:{0},status:{1}", new Object[]{ticket.getTicketId(), ticket.getStatus()});
|
|
|
+ }
|
|
|
+ // 核销优惠券
|
|
|
+ String couponIds = verifyUserCoupon(orderSettleVO.getCouponList());
|
|
|
+
|
|
|
+ UserTicketOrder ticketOrder = new UserTicketOrder();
|
|
|
+ ticketOrder.setOrderId(bizIdGenerator.newId());
|
|
|
+ ticketOrder.setUserId(userId);
|
|
|
+ ticketOrder.setTitle(ticket.getTitle());
|
|
|
+ ticketOrder.setBoxId(ticket.getBoxId());
|
|
|
+ ticketOrder.setOrderAmt(orderSettleVO.getOrderAmt());
|
|
|
+ ticketOrder.setDiscountAmt(orderSettleVO.getDiscountAmt());
|
|
|
+ ticketOrder.setPayAmt(orderSettleVO.getPayAmt());
|
|
|
+ ticketOrder.setTicketNum(1);
|
|
|
+ ticketOrder.setMemo("");
|
|
|
+ ticketOrder.setResource(TicketTypeEnum.OFFLINE);
|
|
|
+ ticketOrder.setCouponInfo(couponIds);
|
|
|
+ ticketOrder.setStatus(UserTicketOrderStatusEnum.NOT_PAY);
|
|
|
+ save(ticketOrder);
|
|
|
+
|
|
|
+ // 查询用户的所属经销商,线上票直接查询
|
|
|
+ ChannelUserRel channelUserRel = channelUserRelService.getOne(new LambdaQueryWrapper<ChannelUserRel>()
|
|
|
+ .eq(ChannelUserRel::getUserId, userId));
|
|
|
+ UserTicketOrderItem orderItem = new UserTicketOrderItem();
|
|
|
+ orderItem.setItemId(bizIdGenerator.newId());
|
|
|
+ orderItem.setOrderId(ticketOrder.getOrderId());
|
|
|
+ orderItem.setUserId(userId);
|
|
|
+ orderItem.setBoxId(ticket.getBoxId());
|
|
|
+ orderItem.setTicketId(ticket.getTicketId());
|
|
|
+ orderItem.setChannelId(null == channelUserRel ? null : channelUserRel.getChannelId());
|
|
|
+ userTicketOrderItemService.save(orderItem);
|
|
|
+ return ticketOrder.getOrderId();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String verifyUserCoupon (List<UserCouponVO> userCouponVOList) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (UserCouponVO userCouponVO : userCouponVOList) {
|
|
|
+ UserCoupon userCoupon = userCouponService.getById(userCouponVO.getId());
|
|
|
+ userCoupon.setVerifyTime(new Date());
|
|
|
+ userCoupon.setStatus(UserCouponStatusEnum.USED);
|
|
|
+ boolean rst = userCouponService.updateById(userCoupon);
|
|
|
+ if (!rst) {
|
|
|
+ LogUtil.error(logger, "盲票购买订单创建时,核销优惠券失败。userCoupon:{0}", new Object[]{JSONObject.toJSONString(userCoupon)});
|
|
|
+ throw new ServiceException("盲票购买订单创建时,核销优惠券失败");
|
|
|
+ }
|
|
|
+ sb.append(userCouponVO.getId()).append(",");
|
|
|
+ }
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ return sb.substring(0, sb.length() -1);
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public boolean cancelOrder(String orderId) {
|
|
|
+ UserTicketOrder userTicketOrder = getById(orderId);
|
|
|
+ if (userTicketOrder.getStatus() != UserTicketOrderStatusEnum.NOT_PAY) {
|
|
|
+ LogUtil.warn(logger, "取消购票订单时,订单状态不是待支付,忽略。orderId:{0}, status:{1}", new Object[]{orderId, userTicketOrder.getStatus()});
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(userTicketOrder.getCouponInfo())) {
|
|
|
+ // 优惠券反核销
|
|
|
+ List<String> userCouponIds = Arrays.asList(userTicketOrder.getCouponInfo().split(","));
|
|
|
+ boolean rst = userCouponService.update(new LambdaUpdateWrapper<UserCoupon>()
|
|
|
+ .set(UserCoupon::getStatus, UserCouponStatusEnum.UNUSED)
|
|
|
+ .set(UserCoupon::getVerifyTime, null)
|
|
|
+ .in(UserCoupon::getId, userCouponIds));
|
|
|
+ if (!rst) {
|
|
|
+ LogUtil.error(logger, "盲票购买订单取消时,反核销优惠券失败。orderId:{0}, userCouponIds:{1}", new Object[]{orderId, userTicketOrder.getCouponInfo()});
|
|
|
+ throw new ServiceException("盲票购买订单取消时,反核销优惠券失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (userTicketOrder.getResource() == TicketTypeEnum.ONLINE) {
|
|
|
+ // TODO 线上票库存回滚,此处需要按票组累计起来回滚
|
|
|
+ TicketBox ticketBox = ticketBoxService.getById(userTicketOrder.getBoxId());
|
|
|
+ ticketBoxService.update(new LambdaUpdateWrapper<TicketBox>().set(TicketBox::getSaleQty, ticketBox.getSaleQty() - userTicketOrder.getTicketNum())
|
|
|
+ .set(ticketBox.getStatus() == TicketBoxStatusEnum.PUT_OFF && ticketBox.getManualOff() != 1,TicketBox::getStatus, TicketBoxStatusEnum.PUT_ON)
|
|
|
+ .eq(TicketBox::getBoxId, ticketBox.getBoxId()).eq(TicketBox::getSaleQty, ticketBox.getSaleQty()));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean rst = update(new LambdaUpdateWrapper<UserTicketOrder>().set(UserTicketOrder::getStatus, UserTicketOrderStatusEnum.CANCELED)
|
|
|
+ .eq(UserTicketOrder::getOrderId, orderId).eq(UserTicketOrder::getStatus, UserTicketOrderStatusEnum.NOT_PAY));
|
|
|
+ if (!rst) {
|
|
|
+ LogUtil.error(logger, "盲票购买订单取消时,更新订单状态失败。orderId:{0}", orderId);
|
|
|
+ throw new ServiceException("盲票购买订单取消时,更新订单状态失败");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean paySuccess(PayOrder payOrder) {
|
|
|
+ UserTicketOrder ticketOrder = getById(payOrder.getBizId());
|
|
|
+ if (null == ticketOrder || ticketOrder.getStatus() != UserTicketOrderStatusEnum.NOT_PAY) {
|
|
|
+ LogUtil.error(logger, "支付回调用户购票订单处理,订单状态异常,不是待支付。payOrder:{0}, channelOrder:{1}",
|
|
|
+ JSONObject.toJSONString(payOrder), JSONObject.toJSONString(ticketOrder));
|
|
|
+ throw new ServiceException("支付回调用户购票订单处理,订单状态异常,不是待支付。orderId:" + payOrder.getBizId());
|
|
|
+ }
|
|
|
+ // 线上票,要先分配票ticketId
|
|
|
+ if (ticketOrder.getResource() == TicketTypeEnum.ONLINE) {
|
|
|
+ List<UserTicketOrderItem> orderItemList = userTicketOrderItemService.list(new LambdaQueryWrapper<UserTicketOrderItem>()
|
|
|
+ .eq(UserTicketOrderItem::getOrderId, ticketOrder.getOrderId()));
|
|
|
+ }
|
|
|
+ // 更新订单状态为已完成
|
|
|
+
|
|
|
+ // 开幸运数字
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|