记得上下班打卡 | git大法好,push需谨慎

Commit a93c81ef authored by wangyifan's avatar wangyifan

kylin模块 拼团查询相关功能

parent dedd5794
......@@ -99,6 +99,8 @@ public class GroupBuyStatusConst {
public static final Integer JOINED = 0;
/** 已退款(拼单中退款/拼成后退款) */
public static final Integer REFUNDED = 1;
/** 已取消(支付超时/用户取消订单) */
public static final Integer CANCELLED = 2;
private MemberStatus() {
}
......
......@@ -32,6 +32,12 @@ public class KylinRedisConst {
public static final String ORDER_REFUND_BY_ORDER_ID = "kylin:order:refund:orderId:";
public static final String ORDER_REFUND = "kylin:order:refund:orderRefundsId:";
//拼团相关开始
public static final String GROUP_BUY_ACTIVITY = "kylin:groupBuy:activity:id:";
public static final String GROUP_BUY_ORDER = "kylin:groupBuy:order:id:";
public static final String GROUP_BUY_ORDER_LOCK = "kylin:groupBuy:lock:";
public static final String GROUP_BUY_ORDER_SHARE = "kylin:groupBuy:order:share:";
public static final String CAMERA_DEVICES = "kylin:cameraDevices:list";
public static final String CAMERA_DEVICES_FIELD = "kylin:cameraDevices:fieldId:";
public static final String CAMERA_DEVICE_GB_INFO = "kylin:cameraDevices:gbId:";
......
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 拼团成员简要信息(头像+ID)。
*/
@Data
public class GroupBuyMemberUserInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户ID")
private String userId;
@ApiModelProperty(value = "头像URL")
private String avatar;
@ApiModelProperty(value = "昵称")
private String nickname;
}
......@@ -18,6 +18,12 @@ public class KylinGroupBuyMemberVo implements Serializable {
@ApiModelProperty(value = "用户ID")
private String userId;
@ApiModelProperty(value = "昵称")
private String nickname;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "订单ID")
private String orderTicketsId;
......
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 我的拼团列表项(/my 用)。
*/
@Data
public class KylinGroupBuyMyGroupVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "拼团订单ID")
private String groupOrderId;
@ApiModelProperty(value = "活动ID")
private String activityId;
@ApiModelProperty(value = "团长用户ID")
private String leaderUserId;
@ApiModelProperty(value = "目标成团人数")
private Integer targetCount;
@ApiModelProperty(value = "当前参团人数")
private Integer currentCount;
@ApiModelProperty(value = "状态 0拼单中 1拼成 2失败 3已取消")
private Integer status;
@ApiModelProperty(value = "过期时间")
private String expiresAt;
@ApiModelProperty(value = "是否团长 1是 0否")
private Integer isLeader;
@ApiModelProperty(value = "成员头像列表")
private List<GroupBuyMemberUserInfoVo> memberBriefs;
}
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 拼单轮播卡片(/pending 用)。
*/
@Data
public class KylinGroupBuyOrderCardVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "拼团订单ID")
private String groupOrderId;
@ApiModelProperty(value = "活动ID")
private String activityId;
@ApiModelProperty(value = "团长用户ID")
private String leaderUserId;
@ApiModelProperty(value = "目标成团人数")
private Integer targetCount;
@ApiModelProperty(value = "当前参团人数")
private Integer currentCount;
@ApiModelProperty(value = "分享token")
private String shareToken;
}
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* 拼团详情(/detail 用)。
*/
@Data
public class KylinGroupBuyOrderDetailVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "拼团订单ID")
private String groupOrderId;
@ApiModelProperty(value = "活动ID")
private String activityId;
@ApiModelProperty(value = "团长用户ID")
private String leaderUserId;
@ApiModelProperty(value = "目标成团人数")
private Integer targetCount;
@ApiModelProperty(value = "当前参团人数")
private Integer currentCount;
@ApiModelProperty(value = "状态 0拼单中 1拼成 2失败 3已取消")
private Integer status;
@ApiModelProperty(value = "是否公开 1公开 0私密")
private Integer isPublic;
@ApiModelProperty(value = "过期时间")
private String expiresAt;
@ApiModelProperty(value = "创建时间")
private String createdAt;
@ApiModelProperty(value = "演出ID")
private String performanceId;
@ApiModelProperty(value = "演出名称")
private String performanceName;
@ApiModelProperty(value = "场次ID")
private String timeId;
@ApiModelProperty(value = "场次名称")
private String timeTitle;
@ApiModelProperty(value = "票种ID")
private String ticketId;
@ApiModelProperty(value = "票种名称")
private String ticketName;
@ApiModelProperty(value = "原价")
private BigDecimal originalPrice;
@ApiModelProperty(value = "拼团单价")
private BigDecimal groupBuyPrice;
@ApiModelProperty(value = "当前用户是否团长 1是 0否")
private Integer isLeader;
@ApiModelProperty(value = "拼团成员信息")
private List<GroupBuyMemberUserInfoVo> members;
}
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class KylinGroupBuyOrderVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "拼团订单ID")
private String groupOrderId;
@ApiModelProperty(value = "活动ID")
private String activityId;
@ApiModelProperty(value = "团长用户ID")
private String leaderUserId;
@ApiModelProperty(value = "团长订单ID")
private String orderTicketsId;
@ApiModelProperty(value = "场次ID")
private String timeId;
@ApiModelProperty(value = "票种ID")
private String ticketId;
@ApiModelProperty(value = "目标成团人数")
private Integer targetCount;
@ApiModelProperty(value = "当前参团人数")
private Integer currentCount;
@ApiModelProperty(value = "状态 0拼单中 1拼成 2失败 3已取消")
private Integer status;
@ApiModelProperty(value = "是否公开 1公开 0私密")
private Integer isPublic;
@ApiModelProperty(value = "分享token")
private String shareToken;
@ApiModelProperty(value = "过期时间")
private String expiresAt;
@ApiModelProperty(value = "成员")
private List<KylinGroupBuyMemberVo> members;
@ApiModelProperty(value = "创建时间")
private String createdAt;
@ApiModelProperty(value = "更新时间")
private String updatedAt;
}
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class KylinGroupBuyPriceVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "活动ID")
private String activityId;
@ApiModelProperty(value = "场次ID")
private String timeId;
@ApiModelProperty(value = "票种ID")
private String ticketId;
@ApiModelProperty(value = "原价")
private BigDecimal originalPrice;
@ApiModelProperty(value = "拼团单价")
private BigDecimal groupBuyPrice;
@ApiModelProperty(value = "优惠类型")
private Integer discountType;
@ApiModelProperty(value = "优惠值")
private BigDecimal discountValue;
}
package com.liquidnet.service.kylin.dto.vo.groupbuy;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 刷新分享链接响应(/refreshShare 用)。
*/
@Data
public class KylinGroupBuyRefreshShareVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "拼团订单ID")
private String groupOrderId;
@ApiModelProperty(value = "新邀请token")
private String shareToken;
}
package com.liquidnet.service.kylin.service;
public interface GroupBuyNotifyService {
void notifyTimeoutRefund(String groupOrderId);
void notifyLeaderCancelled(String groupOrderId);
}
package com.liquidnet.service.kylin.service;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyActivityVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyPriceVo;
import java.util.List;
public interface IKylinGroupBuyActivityService {
ResponseDto<List<KylinGroupBuyActivityVo>> activities(String performanceId);
ResponseDto<KylinGroupBuyPriceVo> price(String activityId, String timeId, String ticketId);
}
package com.liquidnet.service.kylin.service;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyMyGroupVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderCardVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderDetailVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyRefreshShareVo;
import java.util.List;
public interface IKylinGroupBuyOrderService {
ResponseDto<List<KylinGroupBuyOrderCardVo>> pending(String activityId, String timeId, String ticketId);
ResponseDto<PageInfo<KylinGroupBuyMyGroupVo>> my(Integer page, Integer size);
ResponseDto<KylinGroupBuyOrderDetailVo> detail(String groupOrderId, String shareToken);
ResponseDto<Boolean> cancel(String groupOrderId);
ResponseDto<KylinGroupBuyRefreshShareVo> refreshShare(String groupOrderId);
}
package com.liquidnet.service.kylin.service.partner;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.param.KylinGroupBuyActivityParam;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyActivityVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderVo;
import java.util.List;
import java.util.Map;
public interface IKylinGroupBuyPartnerService {
ResponseDto<PageInfo<KylinGroupBuyActivityVo>> list(String name, Integer status, Integer page, Integer size);
ResponseDto<Map<String, Long>> stats();
ResponseDto<KylinGroupBuyActivityVo> detail(String activityId);
ResponseDto<KylinGroupBuyActivityVo> create(KylinGroupBuyActivityParam param);
ResponseDto<KylinGroupBuyActivityVo> update(KylinGroupBuyActivityParam param);
ResponseDto<Boolean> delete(String activityId);
ResponseDto<Boolean> toggle(String activityId, Integer targetStatus);
ResponseDto<List<KylinGroupBuyOrderVo>> orders(String activityId, Integer status, Integer page, Integer size);
}
......@@ -17,6 +17,9 @@ public class RedisKeyExpireConst {
// kylin:order:list:userId 过期时间为30天
public static final long KYLIN_ORDER_LIST_USERID_EXPIRE = 30 * 24 * 60 * 60;
// kylin:groupBuy 过期时间为30天
public static final long KYLIN_GROUP_BUY_EXPIRE = 30 * 24 * 60 * 60;
// adam:info:enters 过期时间为30天
public static final long ADAM_INFO_ENTERS_EXPIRE = 30 * 24 * 60 * 60;
......
......@@ -39,20 +39,4 @@ public class KylinGroupBuyActivity implements Serializable, Cloneable {
return new KylinGroupBuyActivity();
}
}
public Object[] insertObject() {
return new Object[]{
activityId, name, performanceId, minGroupSize, maxBuyPerUser,
startTime, endTime, launchType, scheduledTime, status,
description, createdAt, updatedAt
};
}
public Object[] updateObject() {
return new Object[]{
name, minGroupSize, maxBuyPerUser, startTime, endTime,
launchType, scheduledTime, status, description, updatedAt,
activityId
};
}
}
......@@ -35,11 +35,4 @@ public class KylinGroupBuyDiscount implements Serializable, Cloneable {
return new KylinGroupBuyDiscount();
}
}
public Object[] insertObject() {
return new Object[]{
discountId, activityId, performanceId, timeId, ticketId,
discountType, discountValue, createdAt
};
}
}
......@@ -34,11 +34,4 @@ public class KylinGroupBuyMember implements Serializable, Cloneable {
return new KylinGroupBuyMember();
}
}
public Object[] insertObject() {
return new Object[]{
memberId, groupOrderId, userId, orderTicketsId,
ticketCount, status, joinTime, createdAt
};
}
}
......@@ -38,12 +38,4 @@ public class KylinGroupBuyOrder implements Serializable, Cloneable {
return new KylinGroupBuyOrder();
}
}
public Object[] insertObject() {
return new Object[]{
groupOrderId, activityId, leaderUserId, orderTicketsId,
targetCount, currentCount, status, isPublic, shareToken,
expiresAt, createdAt, updatedAt
};
}
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinGroupBuyActivity;
public interface KylinGroupBuyActivityMapper extends BaseMapper<KylinGroupBuyActivity> {
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinGroupBuyDiscount;
public interface KylinGroupBuyDiscountMapper extends BaseMapper<KylinGroupBuyDiscount> {
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinGroupBuyMember;
public interface KylinGroupBuyMemberMapper extends BaseMapper<KylinGroupBuyMember> {
}
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinGroupBuyOrder;
public interface KylinGroupBuyOrderMapper extends BaseMapper<KylinGroupBuyOrder> {
}
package com.liquidnet.service.kylin.controller;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.groupbuy.*;
import com.liquidnet.service.kylin.service.IKylinGroupBuyActivityService;
import com.liquidnet.service.kylin.service.IKylinGroupBuyOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.util.List;
@Api(tags = "前端-拼团")
@RestController
@RequestMapping("/groupBuy")
@Validated
public class KylinGroupBuyController {
@Autowired
private IKylinGroupBuyActivityService activityService;
@Autowired
private IKylinGroupBuyOrderService orderService;
@GetMapping("/activities")
@ApiOperation("演出下进行中的拼团活动")
public ResponseDto<List<KylinGroupBuyActivityVo>> activities(
@RequestParam("performanceId") @NotNull(message = "演出ID不能为空") String performanceId) {
return activityService.activities(performanceId);
}
@GetMapping("/orders/pending")
@ApiOperation("待成团公开拼单")
public ResponseDto<List<KylinGroupBuyOrderCardVo>> pending(
@RequestParam("activityId") @NotNull(message = "活动ID不能为空") String activityId,
@RequestParam("timeId") @NotNull(message = "场次ID不能为空") String timeId,
@RequestParam("ticketId") @NotNull(message = "票种ID不能为空") String ticketId) {
return orderService.pending(activityId, timeId, ticketId);
}
@GetMapping("/my")
@ApiOperation("我的拼团列表")
public ResponseDto<PageInfo<KylinGroupBuyMyGroupVo>> my(
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "size", required = false, defaultValue = "20") Integer size) {
return orderService.my(page, size);
}
@GetMapping("/detail")
@ApiOperation("拼团详情")
public ResponseDto<KylinGroupBuyOrderDetailVo> detail(@RequestParam(value = "groupOrderId", required = false) String groupOrderId,
@RequestParam(value = "shareToken", required = false) String shareToken) {
return orderService.detail(groupOrderId, shareToken);
}
@PostMapping("/cancel")
@ApiOperation("团长取消拼团")
public ResponseDto<Boolean> cancel(@RequestParam("groupOrderId") @NotNull(message = "拼团订单ID不能为空") String groupOrderId) {
return orderService.cancel(groupOrderId);
}
@PostMapping("/refreshShare")
@ApiOperation("刷新邀请链接")
public ResponseDto<KylinGroupBuyRefreshShareVo> refreshShare(
@RequestParam("groupOrderId") @NotNull(message = "拼团订单ID不能为空") String groupOrderId) {
return orderService.refreshShare(groupOrderId);
}
@GetMapping("/price")
@ApiOperation("查询拼团价")
public ResponseDto<KylinGroupBuyPriceVo> price(
@RequestParam("activityId") @NotNull(message = "活动ID不能为空") String activityId,
@RequestParam("timeId") @NotNull(message = "场次ID不能为空") String timeId,
@RequestParam("ticketId") @NotNull(message = "票种ID不能为空") String ticketId) {
return activityService.price(activityId, timeId, ticketId);
}
}
package com.liquidnet.service.kylin.service.impl;
import com.liquidnet.service.kylin.service.GroupBuyNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class GroupBuyNotifyServiceImpl implements GroupBuyNotifyService {
@Override
public void notifyTimeoutRefund(String groupOrderId) {
log.info("拼团超时退款通知预留,groupOrderId={}", groupOrderId);
}
@Override
public void notifyLeaderCancelled(String groupOrderId) {
log.info("团长取消拼团通知预留,groupOrderId={}", groupOrderId);
}
}
package com.liquidnet.service.kylin.service.impl;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.kylin.constant.GroupBuyStatusConst;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyActivityVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyDiscountVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyPriceVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.service.IKylinGroupBuyActivityService;
import com.liquidnet.service.kylin.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
@Service
@Slf4j
public class KylinGroupBuyActivityServiceImpl implements IKylinGroupBuyActivityService {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private DataUtils dataUtils;
@Autowired
private RedisUtil redisUtil;
@Override
public ResponseDto<List<KylinGroupBuyActivityVo>> activities(String performanceId) {
Query query = Query.query(Criteria.where("performanceId").is(performanceId)
.and("status").is(GroupBuyStatusConst.ActivityStatus.ACTIVE));
List<KylinGroupBuyActivityVo> list = mongoTemplate.find(query,
KylinGroupBuyActivityVo.class, KylinGroupBuyActivityVo.class.getSimpleName());
return ResponseDto.success(list);
}
@Override
public ResponseDto<KylinGroupBuyPriceVo> price(String activityId, String timeId, String ticketId) {
KylinGroupBuyActivityVo activity = getActiveActivity(activityId);
if (activity == null) {
return ResponseDto.failure("拼团活动不存在或未进行中");
}
KylinGroupBuyDiscountVo discount = findDiscount(activity, timeId, ticketId);
if (discount == null) {
return ResponseDto.failure("该票档不支持拼团");
}
BigDecimal originalPrice = getOriginalPrice(activity.getPerformanceId(), timeId, ticketId);
if (originalPrice == null) {
return ResponseDto.failure(ErrorMapping.get("20004"));
}
KylinGroupBuyPriceVo vo = new KylinGroupBuyPriceVo();
vo.setActivityId(activityId);
vo.setTimeId(timeId);
vo.setTicketId(ticketId);
vo.setOriginalPrice(originalPrice);
vo.setDiscountType(discount.getDiscountType());
vo.setDiscountValue(discount.getDiscountValue());
vo.setGroupBuyPrice(discount.getDiscountValue());
return ResponseDto.success(vo);
}
public KylinGroupBuyActivityVo getActiveActivity(String activityId) {
if (activityId == null) {
return null;
}
String redisKey = KylinRedisConst.GROUP_BUY_ACTIVITY.concat(activityId);
Object obj = redisUtil.get(redisKey);
if (obj != null) {
KylinGroupBuyActivityVo activity = (KylinGroupBuyActivityVo) obj;
return GroupBuyStatusConst.ActivityStatus.ACTIVE.equals(activity.getStatus()) ? activity : null;
}
Query query = Query.query(Criteria.where("activityId").is(activityId)
.and("status").is(GroupBuyStatusConst.ActivityStatus.ACTIVE));
KylinGroupBuyActivityVo activity = mongoTemplate.findOne(query, KylinGroupBuyActivityVo.class,
KylinGroupBuyActivityVo.class.getSimpleName());
if (activity != null) {
redisUtil.set(redisKey, activity, RedisKeyExpireConst.KYLIN_GROUP_BUY_EXPIRE);
}
return activity;
}
public KylinGroupBuyDiscountVo findDiscount(KylinGroupBuyActivityVo activity, String timeId, String ticketId) {
if (activity == null || activity.getDiscounts() == null) {
return null;
}
for (KylinGroupBuyDiscountVo discount : activity.getDiscounts()) {
if (timeId.equals(discount.getTimeId()) && ticketId.equals(discount.getTicketId())) {
return discount;
}
}
return null;
}
public BigDecimal getOriginalPrice(String performanceId, String timeId, String ticketId) {
KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(performanceId);
if (performanceVo == null || performanceVo.getTicketTimeList() == null) {
return null;
}
for (KylinTicketTimesVo timeVo : performanceVo.getTicketTimeList()) {
if (!timeId.equals(timeVo.getTimeId()) || timeVo.getTicketList() == null) {
continue;
}
for (KylinTicketVo ticketVo : timeVo.getTicketList()) {
if (ticketId.equals(ticketVo.getTicketsId())) {
return ticketVo.getPrice();
}
}
}
return null;
}
}
package com.liquidnet.service.kylin.service.impl;
import com.github.pagehelper.PageInfo;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.kylin.constant.GroupBuyStatusConst;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyActivityVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyDiscountVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyMemberVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.GroupBuyMemberUserInfoVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyMyGroupVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderCardVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderDetailVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyOrderVo;
import com.liquidnet.service.kylin.dto.vo.groupbuy.KylinGroupBuyRefreshShareVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.service.GroupBuyNotifyService;
import com.liquidnet.service.kylin.service.IKylinGroupBuyOrderService;
import com.liquidnet.service.kylin.utils.DataUtils;
import com.liquidnet.service.kylin.utils.QueueUtils;
import com.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@Service
@Slf4j
public class KylinGroupBuyOrderServiceImpl implements IKylinGroupBuyOrderService {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private DataUtils dataUtils;
@Autowired
private KylinGroupBuyActivityServiceImpl activityService;
@Autowired
private KylinOrderTicketsRefundServiceImpl refundService;
@Autowired
private GroupBuyNotifyService notifyService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private QueueUtils queueUtils;
@Override
public ResponseDto<List<KylinGroupBuyOrderCardVo>> pending(String activityId, String timeId, String ticketId) {
Query query = Query.query(Criteria.where("activityId").is(activityId)
.and("ticketId").is(ticketId)
.and("timeId").is(timeId)
.and("status").is(GroupBuyStatusConst.OrderStatus.PENDING)
.and("isPublic").is(GroupBuyStatusConst.PublicFlag.PUBLIC));
query.with(Sort.by(Sort.Direction.ASC, "createdAt")).limit(3);
List<KylinGroupBuyOrderVo> orders = mongoTemplate.find(query,
KylinGroupBuyOrderVo.class, KylinGroupBuyOrderVo.class.getSimpleName());
List<KylinGroupBuyOrderCardVo> result = new ArrayList<>();
for (KylinGroupBuyOrderVo o : orders) {
if (o.getCurrentCount() >= o.getTargetCount()) continue;
if (isExpired(o)) continue;
KylinGroupBuyOrderCardVo card = new KylinGroupBuyOrderCardVo();
card.setGroupOrderId(o.getGroupOrderId());
card.setActivityId(o.getActivityId());
card.setLeaderUserId(o.getLeaderUserId());
card.setTargetCount(o.getTargetCount());
card.setCurrentCount(o.getCurrentCount());
card.setShareToken(o.getShareToken());
result.add(card);
}
return ResponseDto.success(result);
}
@Override
public ResponseDto<PageInfo<KylinGroupBuyMyGroupVo>> my(Integer page, Integer size) {
String uid = CurrentUtil.getCurrentUid();
Criteria criteria = new Criteria().orOperator(
Criteria.where("leaderUserId").is(uid),
Criteria.where("members.userId").is(uid));
Query countQuery = Query.query(criteria);
long total = mongoTemplate.count(countQuery, KylinGroupBuyOrderVo.class,
KylinGroupBuyOrderVo.class.getSimpleName());
Query dataQuery = Query.query(criteria).with(Sort.by(Sort.Direction.DESC, "createdAt"));
if (page != null && size != null && page > 0 && size > 0) {
dataQuery.skip((long) (page - 1) * size).limit(size);
}
List<KylinGroupBuyOrderVo> orders = mongoTemplate.find(dataQuery,
KylinGroupBuyOrderVo.class, KylinGroupBuyOrderVo.class.getSimpleName());
List<KylinGroupBuyMyGroupVo> result = new ArrayList<>();
for (KylinGroupBuyOrderVo o : orders) {
KylinGroupBuyMyGroupVo vo = new KylinGroupBuyMyGroupVo();
vo.setGroupOrderId(o.getGroupOrderId());
vo.setActivityId(o.getActivityId());
vo.setLeaderUserId(o.getLeaderUserId());
vo.setTargetCount(o.getTargetCount());
vo.setCurrentCount(o.getCurrentCount());
vo.setStatus(o.getStatus());
vo.setExpiresAt(o.getExpiresAt());
vo.setIsLeader(uid.equals(o.getLeaderUserId()) ? 1 : 0);
if (o.getMembers() != null) {
List<GroupBuyMemberUserInfoVo> memberUserList = new ArrayList<>();
for (KylinGroupBuyMemberVo m : o.getMembers()) {
GroupBuyMemberUserInfoVo b = new GroupBuyMemberUserInfoVo();
b.setUserId(m.getUserId());
b.setAvatar(m.getAvatar());
b.setNickname(m.getNickname());
memberUserList.add(b);
}
vo.setMemberBriefs(memberUserList);
}
result.add(vo);
}
PageInfo<KylinGroupBuyMyGroupVo> pageInfo = new PageInfo<>(result);
pageInfo.setTotal(total);
return ResponseDto.success(pageInfo);
}
@Override
public ResponseDto<KylinGroupBuyOrderDetailVo> detail(String groupOrderId, String shareToken) {
KylinGroupBuyOrderVo order = getOrderForJoin(groupOrderId, shareToken);
if (order == null) return ResponseDto.failure("拼团不存在");
KylinGroupBuyActivityVo activity = findActivity(order.getActivityId());
KylinPerformanceVo performance = dataUtils.getPerformanceVo(order.getActivityId() != null ? activity.getPerformanceId() : null);
KylinGroupBuyOrderDetailVo vo = new KylinGroupBuyOrderDetailVo();
vo.setGroupOrderId(order.getGroupOrderId());
vo.setActivityId(order.getActivityId());
vo.setLeaderUserId(order.getLeaderUserId());
vo.setTargetCount(order.getTargetCount());
vo.setCurrentCount(order.getCurrentCount());
vo.setStatus(order.getStatus());
vo.setIsPublic(order.getIsPublic());
vo.setExpiresAt(order.getExpiresAt());
vo.setCreatedAt(order.getCreatedAt());
vo.setTimeId(order.getTimeId());
vo.setTicketId(order.getTicketId());
vo.setIsLeader(CurrentUtil.getCurrentUid().equals(order.getLeaderUserId()) ? 1 : 0);
if (performance != null) {
vo.setPerformanceName(performance.getTitle());
fillTicketInfo(performance, order.getTimeId(), order.getTicketId(), vo);
}
if (activity != null) {
vo.setPerformanceId(activity.getPerformanceId());
KylinGroupBuyDiscountVo discount = activityService.findDiscount(activity, order.getTimeId(), order.getTicketId());
vo.setGroupBuyPrice(discount != null ? discount.getDiscountValue() : null);
}
if (order.getMembers() != null) {
List<GroupBuyMemberUserInfoVo> members = new ArrayList<>();
for (KylinGroupBuyMemberVo m : order.getMembers()) {
GroupBuyMemberUserInfoVo mu = new GroupBuyMemberUserInfoVo();
mu.setUserId(m.getUserId());
mu.setNickname(m.getNickname());
mu.setAvatar(m.getAvatar());
members.add(mu);
}
vo.setMembers(members);
}
return ResponseDto.success(vo);
}
@Override
public ResponseDto<Boolean> cancel(String groupOrderId) {
String uid = CurrentUtil.getCurrentUid();
KylinGroupBuyOrderVo order = findOrder(groupOrderId);
if (order == null) return ResponseDto.failure("拼团不存在");
if (!uid.equals(order.getLeaderUserId())) return ResponseDto.failure("仅团长可取消拼团");
if (GroupBuyStatusConst.OrderStatus.SUCCESS.equals(order.getStatus())) return ResponseDto.failure("拼团已成,不可取消");
if (!GroupBuyStatusConst.OrderStatus.PENDING.equals(order.getStatus())) return ResponseDto.failure("当前状态不可取消");
order.setStatus(GroupBuyStatusConst.OrderStatus.CANCELLED);
order.setUpdatedAt(now());
saveOrder(order);
refundAllGroupMembers(order, "团长取消拼团,全额退款");
notifyLeaderCancelled(order.getGroupOrderId());
return ResponseDto.success(true);
}
@Override
public ResponseDto<KylinGroupBuyRefreshShareVo> refreshShare(String groupOrderId) {
String uid = CurrentUtil.getCurrentUid();
KylinGroupBuyOrderVo order = findOrder(groupOrderId);
if (order == null) return ResponseDto.failure("拼团不存在");
if (!uid.equals(order.getLeaderUserId())) return ResponseDto.failure("仅团长可刷新邀请链接");
if (!GroupBuyStatusConst.OrderStatus.PENDING.equals(order.getStatus())
&& !GroupBuyStatusConst.OrderStatus.PREPARE.equals(order.getStatus())) {
return ResponseDto.failure("当前状态不可刷新邀请链接");
}
redisUtil.del(KylinRedisConst.GROUP_BUY_ORDER_SHARE.concat(order.getShareToken()));
order.setShareToken(IDGenerator.nextSnowId());
order.setUpdatedAt(now());
saveOrder(order);
KylinGroupBuyRefreshShareVo vo = new KylinGroupBuyRefreshShareVo();
vo.setGroupOrderId(groupOrderId);
vo.setShareToken(order.getShareToken());
return ResponseDto.success(vo);
}
// ==================== private helpers ====================
private KylinGroupBuyOrderVo getOrderForJoin(String groupOrderId, String shareToken) {
if (shareToken != null) {
Object v = redisUtil.get(KylinRedisConst.GROUP_BUY_ORDER_SHARE.concat(shareToken));
if (v != null) return (KylinGroupBuyOrderVo) v;
} else if (groupOrderId != null) {
Object v = redisUtil.get(KylinRedisConst.GROUP_BUY_ORDER.concat(groupOrderId));
if (v != null) return (KylinGroupBuyOrderVo) v;
}
Criteria c = shareToken != null ? Criteria.where("shareToken").is(shareToken)
: Criteria.where("groupOrderId").is(groupOrderId);
KylinGroupBuyOrderVo order = mongoTemplate.findOne(Query.query(c),
KylinGroupBuyOrderVo.class, KylinGroupBuyOrderVo.class.getSimpleName());
cacheOrder(order);
return order;
}
private KylinGroupBuyOrderVo findOrder(String groupOrderId) {
if (groupOrderId == null) return null;
Object obj = redisUtil.get(KylinRedisConst.GROUP_BUY_ORDER.concat(groupOrderId));
if (obj != null) return (KylinGroupBuyOrderVo) obj;
KylinGroupBuyOrderVo order = mongoTemplate.findOne(
Query.query(Criteria.where("groupOrderId").is(groupOrderId)),
KylinGroupBuyOrderVo.class, KylinGroupBuyOrderVo.class.getSimpleName());
cacheOrder(order);
return order;
}
private KylinGroupBuyActivityVo findActivity(String activityId) {
Object obj = redisUtil.get(KylinRedisConst.GROUP_BUY_ACTIVITY.concat(activityId));
if (obj != null) return (KylinGroupBuyActivityVo) obj;
KylinGroupBuyActivityVo activity = mongoTemplate.findOne(
Query.query(Criteria.where("activityId").is(activityId)),
KylinGroupBuyActivityVo.class, KylinGroupBuyActivityVo.class.getSimpleName());
if (activity != null) redisUtil.set(KylinRedisConst.GROUP_BUY_ACTIVITY.concat(activityId),
activity, RedisKeyExpireConst.KYLIN_GROUP_BUY_EXPIRE);
return activity;
}
private void saveOrder(KylinGroupBuyOrderVo order) {
clearOrderCache(order);
mongoTemplate.getCollection(KylinGroupBuyOrderVo.class.getSimpleName()).updateOne(
Query.query(Criteria.where("groupOrderId").is(order.getGroupOrderId())).getQueryObject(),
new BasicDBObject().append("$set", mongoTemplate.getConverter().convertToMongoType(order)));
sendReplaceOrderSql(order, MQConst.KylinQueue.SQL_ORDER_PAY.getKey());
cacheOrder(order);
}
private void sendReplaceOrderSql(KylinGroupBuyOrderVo order, String queueKey) {
if (order.getOrderTicketsId() == null || order.getExpiresAt() == null) return;
LinkedList<String> sqls = CollectionUtil.linkedListString();
LinkedList<Object[]> od = CollectionUtil.linkedListObjectArr();
LinkedList<Object[]> oi = CollectionUtil.linkedListObjectArr();
LinkedList<Object[]> md = CollectionUtil.linkedListObjectArr();
LinkedList<Object[]> mi = CollectionUtil.linkedListObjectArr();
sqls.add(SqlMapping.get("kylin_group_buy_order.delete"));
od.add(new Object[]{order.getGroupOrderId()});
sqls.add(SqlMapping.get("kylin_group_buy_order.insert"));
oi.add(orderInsertObject(order));
sqls.add(SqlMapping.get("kylin_group_buy_member.delete_by_group"));
md.add(new Object[]{order.getGroupOrderId()});
if (!CollectionUtils.isEmpty(order.getMembers())) {
sqls.add(SqlMapping.get("kylin_group_buy_member.insert"));
for (KylinGroupBuyMemberVo m : order.getMembers()) mi.add(memberInsertObject(m));
queueUtils.sendMsgByRedis(queueKey, SqlMapping.gets(sqls, od, oi, md, mi));
} else {
queueUtils.sendMsgByRedis(queueKey, SqlMapping.gets(sqls, od, oi, md));
}
}
private Object[] orderInsertObject(KylinGroupBuyOrderVo vo) {
return new Object[]{vo.getGroupOrderId(), vo.getActivityId(), vo.getLeaderUserId(),
vo.getOrderTicketsId(), vo.getTargetCount(), vo.getCurrentCount(), vo.getStatus(),
vo.getIsPublic(), vo.getShareToken(),
DateUtil.Formatter.yyyyMMddHHmmss.parse(vo.getExpiresAt()),
DateUtil.Formatter.yyyyMMddHHmmss.parse(vo.getCreatedAt()),
DateUtil.Formatter.yyyyMMddHHmmss.parse(vo.getUpdatedAt())};
}
private Object[] memberInsertObject(KylinGroupBuyMemberVo vo) {
return new Object[]{vo.getMemberId(), vo.getGroupOrderId(), vo.getUserId(),
vo.getOrderTicketsId(), vo.getTicketCount(), vo.getStatus(),
DateUtil.Formatter.yyyyMMddHHmmss.parse(vo.getJoinTime()),
DateUtil.Formatter.yyyyMMddHHmmss.parse(vo.getJoinTime())};
}
private void cacheOrder(KylinGroupBuyOrderVo order) {
if (order == null) return;
redisUtil.set(KylinRedisConst.GROUP_BUY_ORDER.concat(order.getGroupOrderId()), order,
RedisKeyExpireConst.KYLIN_GROUP_BUY_EXPIRE);
redisUtil.set(KylinRedisConst.GROUP_BUY_ORDER_SHARE.concat(order.getShareToken()), order,
RedisKeyExpireConst.KYLIN_GROUP_BUY_EXPIRE);
}
private void clearOrderCache(KylinGroupBuyOrderVo order) {
if (order == null) return;
redisUtil.del(KylinRedisConst.GROUP_BUY_ORDER.concat(order.getGroupOrderId()));
redisUtil.del(KylinRedisConst.GROUP_BUY_ORDER_SHARE.concat(order.getShareToken()));
}
private boolean isExpired(KylinGroupBuyOrderVo order) {
return order.getExpiresAt() != null
&& DateUtil.Formatter.yyyyMMddHHmmss.parse(order.getExpiresAt()).isBefore(LocalDateTime.now());
}
private long restSeconds(KylinGroupBuyOrderVo order) {
if (order.getExpiresAt() == null) return 0L;
return Math.max(0L, java.time.Duration.between(LocalDateTime.now(),
DateUtil.Formatter.yyyyMMddHHmmss.parse(order.getExpiresAt())).getSeconds());
}
private void refundAllGroupMembers(KylinGroupBuyOrderVo order, String reason) {
if (CollectionUtils.isEmpty(order.getMembers())) return;
for (KylinGroupBuyMemberVo member : order.getMembers()) {
KylinOrderTicketVo ticketVo = dataUtils.getOrderTicketVo(member.getOrderTicketsId());
if (ticketVo == null || CollectionUtils.isEmpty(ticketVo.getEntitiesVoList())) continue;
for (KylinOrderTicketEntitiesVo entity : ticketVo.getEntitiesVoList()) {
refundService.sendOrderRefund(ticketVo.getOrderTicketsId(), entity.getOrderTicketEntitiesId(),
reason, "", "", 0, "", "", "", "", "");
}
}
}
private void notifyLeaderCancelled(String groupOrderId) {
try {
notifyService.notifyLeaderCancelled(groupOrderId);
} catch (Exception e) {
log.error("团长取消拼团通知失败 groupOrderId={}", groupOrderId, e);
}
}
private String now() {
return DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now());
}
private void fillTicketInfo(KylinPerformanceVo p, String timeId, String ticketId,
KylinGroupBuyOrderDetailVo vo) {
if (p.getTicketTimeList() == null) return;
for (KylinTicketTimesVo t : p.getTicketTimeList()) {
if (!timeId.equals(t.getTimeId())) continue;
vo.setTimeTitle(t.getTitle());
if (t.getTicketList() == null) return;
for (KylinTicketVo tk : t.getTicketList()) {
if (ticketId.equals(tk.getTicketsId())) {
vo.setTicketName(tk.getTitle());
vo.setOriginalPrice(tk.getPrice());
return;
}
}
return;
}
}
}
......@@ -43,3 +43,10 @@ kylin_order_ticket_entities.update_status_bystation_pad=UPDATE kylin_order_ticke
# ------------------------ \u6F14\u51FA\u9884\u7EA6 ----------------------------
kylin_performance_subscribe.insert=INSERT INTO kylin_performance_subscribe(performance_id,ticket_times_id,tickets_id,user_id,type,device_tokens,push_range,push_time,push_title,is_push)VALUES(?,?,?,?,?,?,?,?,?,?)
kylin_performance_subscribe.delete=DELETE FROM kylin_performance_subscribe WHERE performance_id= ? and ticket_times_id = ? and user_id = ?;
# ------------------------\u6F14\u51FA\u7968\u62FC\u56E2----------------------------
kylin_group_buy_order.delete=DELETE FROM kylin_group_buy_order WHERE group_order_id = ?
kylin_group_buy_order.insert=INSERT INTO kylin_group_buy_order (group_order_id,activity_id,leader_user_id,order_tickets_id,target_count,current_count,status,is_public,share_token,expires_at,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
kylin_group_buy_order.update_status=UPDATE kylin_group_buy_order SET status = ?, updated_at = ? WHERE group_order_id = ? AND status = ?
kylin_group_buy_member.delete_by_group=DELETE FROM kylin_group_buy_member WHERE group_order_id = ?
kylin_group_buy_member.insert=INSERT INTO kylin_group_buy_member (member_id,group_order_id,user_id,order_tickets_id,ticket_count,status,join_time,created_at) VALUES (?,?,?,?,?,?,?,?)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment