|
|
@@ -32,6 +32,7 @@ import com.cyksj.mapper.vip.VipGoodsSkuMapper;
|
|
|
import com.cyksj.mapper.vip.VipUserMapper;
|
|
|
import com.cyksj.model.dto.ErrorNetflixChangeOtherSkuTicketDto;
|
|
|
import com.cyksj.model.dto.NetflixRecoverReceivedGptConditionDto;
|
|
|
+import com.cyksj.model.dto.OrderRefundDto;
|
|
|
import com.cyksj.model.dto.TicketChangeDto;
|
|
|
import com.cyksj.model.entity.*;
|
|
|
import com.cyksj.model.manage.views.AccountView;
|
|
|
@@ -2385,6 +2386,273 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void youtubeSubmitFrozen(ErrorNetflixChangeReq req) {
|
|
|
+ Long relationId = req.getRelationId();
|
|
|
+ Long userId = req.getUserId();
|
|
|
+ //校验账号
|
|
|
+ GroupsRelationView netflixRelationView = checkYoutubeTime(relationId, userId);
|
|
|
+ if (netflixRelationView.getIsFrozen()) {
|
|
|
+ throw BusinessRuntimeException.getInstance("您的车票已冻结");
|
|
|
+ }
|
|
|
+ Date expiryTime = netflixRelationView.getExpiryTime();
|
|
|
+ OrderDon orderDon = orderDonMapper.selectById(netflixRelationView.getNfOriOrderId());
|
|
|
+ Long betweenDay;
|
|
|
+ if (expiryTime == null) {
|
|
|
+ //用订单时间
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ if (expiryTime == null) {
|
|
|
+ if (sku.getDays() != null) {
|
|
|
+ expiryTime = DateUtil.offsetDay(orderDon.getCreatedTime(), sku.getDays());
|
|
|
+ } else {
|
|
|
+ expiryTime = DateUtil.offsetMonth(orderDon.getCreatedTime(), sku.getMonths());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ betweenDay= DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
|
|
|
+
|
|
|
+ groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
|
|
|
+ .set(GroupsRelation::getIsFrozen, Boolean.TRUE)
|
|
|
+ //冻结12个月
|
|
|
+ .set(GroupsRelation::getUnfrozenTime, DateUtil.offsetMonth(DateTime.now(), 12))
|
|
|
+ .set(betweenDay != null, GroupsRelation::getReservedDays, betweenDay)
|
|
|
+ .eq(GroupsRelation::getId, netflixRelationView.getId())
|
|
|
+ .eq(GroupsRelation::getUserId, netflixRelationView.getUserId()));
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ public void errorYoutubeChangeOtherTicket(ErrorNetflixChangeReq req) throws Exception {
|
|
|
+ Long relationId = req.getRelationId();
|
|
|
+ Long userId = req.getUserId();
|
|
|
+ //校验账号
|
|
|
+ GroupsRelationView relationView = checkYoutubeTime(relationId, userId);
|
|
|
+ String key = RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getName() + relationId;
|
|
|
+ if (!redisService.setNx(key, relationId, RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getTimeout())) {
|
|
|
+ throw BusinessRuntimeException.getInstance("正在更换其他车票中..");
|
|
|
+ }
|
|
|
+ Date expiryTime = relationView.getExpiryTime();
|
|
|
+ SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
|
|
|
+ .eq(SysConfig::getSysKey, Constant.ERROR_YOUTUBE_CHANGE_OTHER_SKU_KEY)
|
|
|
+ .last("limit 1"));
|
|
|
+ List<ErrorNetflixChangeOtherSkuTicketDto> errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class);
|
|
|
+ //替换车票
|
|
|
+ ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0);
|
|
|
+ List<Long> skuIds = errorNetflixChangeOtherSkuTicketDto.getSkuIds();
|
|
|
+ try {
|
|
|
+ for (Long skuId : skuIds) {
|
|
|
+ TicketChangeDto changeDto = getTicketAndGenerateOrder(userId, skuId, null, null);
|
|
|
+ if (changeDto == null) {
|
|
|
+ throw BusinessRuntimeException.getInstance("系统繁忙,请重试");
|
|
|
+ }
|
|
|
+ //替换记录
|
|
|
+ NetflixUserChangeOtherTicketRecord changeOtherTicketRecord = new NetflixUserChangeOtherTicketRecord();
|
|
|
+ changeOtherTicketRecord.setUserId(userId);
|
|
|
+ changeOtherTicketRecord.setRelationId(relationId);
|
|
|
+ changeOtherTicketRecord.setOtherRelationId(changeDto.getOtherRelationId());
|
|
|
+ changeOtherTicketRecord.setRelateOrderId(changeDto.getOtherOrderId());
|
|
|
+ //该车票订单id
|
|
|
+ changeOtherTicketRecord.setOrderId(relationView.getNfOriOrderId());
|
|
|
+ changeOtherTicketRecord.setStartTime(relationView.getStartTime());
|
|
|
+ changeOtherTicketRecord.setExpiryTime(expiryTime);
|
|
|
+ netflixUserChangeOtherTicketRecordMapper.insert(changeOtherTicketRecord);
|
|
|
+ }
|
|
|
+ //清除车票
|
|
|
+ GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
|
|
|
+ .eq(GroupsRelation::getId, relationId)
|
|
|
+ .eq(GroupsRelation::getUserId, relationView.getUserId())
|
|
|
+ .last("limit 1"));
|
|
|
+ if (clearRelation != null) {
|
|
|
+ clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace);
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ redisService.del(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void errorYoutubeRefund(ErrorNetflixChangeReq req) throws Exception {
|
|
|
+ Long relationId = req.getRelationId();
|
|
|
+ Long userId = req.getUserId();
|
|
|
+ //校验状态
|
|
|
+ GroupsRelationView relationView = checkYoutubeTime(relationId, userId);
|
|
|
+ Long ticketUserId = relationView.getUserId();
|
|
|
+ OrderDon orderDon = orderDonMapper.selectById(relationView.getNfOriOrderId());
|
|
|
+ if (orderDon != null) {
|
|
|
+ //paypal 或者超过一年 联系客服退款
|
|
|
+ if (orderDon.getType() == OrderDon.Type.PAYPAL) {
|
|
|
+ throw BusinessRuntimeException.getInstance("请联系客服退款");
|
|
|
+ }
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ OrderRefundDto orderRefundDto = getYoutubeRefundInfo(relationView, orderDon, sku);
|
|
|
+ BigDecimal refundBalance = orderRefundDto.getRefundBalance();
|
|
|
+ BigDecimal refundMoney = orderRefundDto.getRefundMoney();
|
|
|
+ //超过订单金额 让联系客服退款
|
|
|
+ if (refundMoney.compareTo(orderDon.getMoney()) > 0) {
|
|
|
+ throw BusinessRuntimeException.getInstance("请联系客服退款");
|
|
|
+ }
|
|
|
+ String outNo = StrUtil.EMPTY;
|
|
|
+ //金额退款
|
|
|
+ if (refundMoney.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ //调用第三方接口退款
|
|
|
+ OrderRefundReq refundReq = new OrderRefundReq();
|
|
|
+ refundReq.setRefundMoney(refundMoney);
|
|
|
+ refundReq.setRefundType("money");
|
|
|
+ try {
|
|
|
+ outNo = orderRefundService.centerRefund(refundReq, orderDon);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw BusinessRuntimeException.getInstance("请联系客服退款");
|
|
|
+ }
|
|
|
+ orderDon.setRefundMoney(refundMoney);
|
|
|
+ }
|
|
|
+ //余额退款
|
|
|
+ if (refundBalance.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ userBenefitsService.addUserBalance(ticketUserId, refundBalance, UserBalanceSourceRecord.Source.yt_refund, 0L, orderDon.getId(), UserBalanceSourceRecord.Source.yt_refund.getDesc(), true);
|
|
|
+ }
|
|
|
+ orderDon.setStatus(OrderDon.Status.refund);
|
|
|
+ if (refundBalance.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ orderDon.setRefundBalance(refundBalance);
|
|
|
+ }
|
|
|
+ orderDon.setRefundDesc("油管掉会员退款");
|
|
|
+ orderDonMapper.updateById(orderDon);
|
|
|
+ //记录退款类型
|
|
|
+ String refundType = getRefundType(refundMoney, refundBalance, orderDon);
|
|
|
+ orderRefundService.refundRecord(orderDon, refundMoney, refundBalance, "系统", goodsDon, sku, outNo, refundType, null);
|
|
|
+ //清除车票
|
|
|
+ GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
|
|
|
+ .eq(GroupsRelation::getId, relationId)
|
|
|
+ .eq(GroupsRelation::getUserId, relationView.getUserId())
|
|
|
+ .last("limit 1"));
|
|
|
+ if (clearRelation != null) {
|
|
|
+ clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.yt_refund);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private OrderRefundDto getYoutubeRefundInfo(GroupsRelationView relationView, OrderDon orderDon, GoodsDonSku sku) {
|
|
|
+ OrderRefundDto orderRefundDto = new OrderRefundDto();
|
|
|
+ Date expiryTime = relationView.getExpiryTime();
|
|
|
+ DateTime now = DateTime.now();
|
|
|
+ if (relationView.getIsFrozen()) {
|
|
|
+ Integer reservedDays = relationView.getReservedDays();
|
|
|
+ //处理边界
|
|
|
+ if (relationView.getReservedDays() == 365) {
|
|
|
+ reservedDays = 364;
|
|
|
+ }
|
|
|
+ expiryTime = DateUtil.offsetDay(now, reservedDays);
|
|
|
+ }
|
|
|
+ if (expiryTime == null) {
|
|
|
+ if (sku.getDays() != null) {
|
|
|
+ expiryTime = DateUtil.offsetDay(orderDon.getCreatedTime(), sku.getDays());
|
|
|
+ } else {
|
|
|
+ expiryTime = DateUtil.offsetMonth(orderDon.getCreatedTime(), sku.getMonths());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //剩余几个月
|
|
|
+ Long remainMonths = DateUtil.betweenMonth(now, expiryTime, false) + 1;
|
|
|
+ BigDecimal refundBalance = BigDecimal.ZERO;
|
|
|
+ BigDecimal refundMoney = BigDecimal.ZERO;
|
|
|
+ //订单金额
|
|
|
+ BigDecimal money = orderDon.getMoney();
|
|
|
+ BigDecimal balance = Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO);
|
|
|
+ BigDecimal orderTotalMoney = money.add(balance);
|
|
|
+ //2年
|
|
|
+ if ((sku.getDays() != null && sku.getDays() == 730) || (sku.getMonths() != null && sku.getMonths() == 24)) {
|
|
|
+ if (remainMonths > 12) {
|
|
|
+ //兑换码订单
|
|
|
+ if (orderTotalMoney.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ orderTotalMoney = sku.getPrice();
|
|
|
+ }
|
|
|
+ BigDecimal totalRefundMoney = orderTotalMoney.divide(BigDecimal.valueOf(2), RoundingMode.DOWN);
|
|
|
+ if (money.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ refundBalance = refundBalance.add(totalRefundMoney);
|
|
|
+ } else {
|
|
|
+ refundMoney = totalRefundMoney;
|
|
|
+ if (totalRefundMoney.compareTo(money) > 0) {
|
|
|
+ refundMoney = money;
|
|
|
+ refundBalance = totalRefundMoney.subtract(money);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ remainMonths = remainMonths - 12;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (remainMonths >= 1 && remainMonths <= 6) {
|
|
|
+ //1-6月买的 退100余额
|
|
|
+ refundBalance = refundBalance.add(BigDecimal.valueOf(10000));
|
|
|
+ } else if (remainMonths >= 7 && remainMonths <= 11) {
|
|
|
+ //7-11月买的 退150余额
|
|
|
+ refundBalance = refundBalance.add(BigDecimal.valueOf(15000));
|
|
|
+ } else {
|
|
|
+ //12月买的 退200余额
|
|
|
+ refundBalance = refundBalance.add(BigDecimal.valueOf(20000));
|
|
|
+ }
|
|
|
+ //超过订单金额 计算剩余的余额 排除兑换码
|
|
|
+ if (orderTotalMoney.compareTo(BigDecimal.ZERO) > 0 && refundMoney.add(refundBalance).compareTo(orderTotalMoney) > 0) {
|
|
|
+ refundBalance = orderTotalMoney.subtract(refundMoney);
|
|
|
+ }
|
|
|
+ orderRefundDto.setRefundMoney(refundMoney);
|
|
|
+ orderRefundDto.setRefundBalance(refundBalance);
|
|
|
+ return orderRefundDto;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<GoodsCategorySkuView> getYoutubeReplaceOtherSkus() throws Exception {
|
|
|
+ SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
|
|
|
+ .eq(SysConfig::getSysKey, Constant.ERROR_YOUTUBE_CHANGE_OTHER_SKU_KEY)
|
|
|
+ .last("limit 1"));
|
|
|
+ List<ErrorNetflixChangeOtherSkuTicketDto> errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class);
|
|
|
+ ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0);
|
|
|
+ List<GoodsCategorySkuView> goodsCategorySkuViews = beanSearcher.searchAll(GoodsCategorySkuView.class, MapUtils.builder()
|
|
|
+ .field(GoodsCategorySkuView::getSkuId, errorNetflixChangeOtherSkuTicketDto.getSkuIds()).op(Operator.InList)
|
|
|
+ .orderBy(GoodsCategorySkuView::getPrice).desc()
|
|
|
+ .build());
|
|
|
+ return goodsCategorySkuViews;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OrderRefundDto getYoutubeRefundInfo(long userId, Long relationId) {
|
|
|
+ //校验状态
|
|
|
+ List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
|
|
|
+ GroupsRelationView relationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
|
|
|
+ .field(GroupsRelationView::getId, relationId)
|
|
|
+ .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
|
|
|
+ .field(GroupsRelationView::getGoodsId, Constant.YOUTUBE_GOODS_ID)
|
|
|
+ .build());
|
|
|
+ if (relationView != null) {
|
|
|
+ OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class).in(OrderDon::getUserId, userIdList).eq(OrderDon::getRelationId, relationId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).orderByDesc(OrderDon::getId).last("limit 1"));
|
|
|
+ if (orderDon != null) {
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ OrderRefundDto orderRefundDto = getYoutubeRefundInfo(relationView, orderDon, sku);
|
|
|
+ return orderRefundDto;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private GroupsRelationView checkYoutubeTime(Long relationId, Long userId) {
|
|
|
+ List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
|
|
|
+ GroupsRelationView relationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
|
|
|
+ .field(GroupsRelationView::getId, relationId)
|
|
|
+ .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
|
|
|
+ .field(GroupsRelationView::getGoodsId, Constant.YOUTUBE_GOODS_ID)
|
|
|
+ .build());
|
|
|
+ if (relationView == null) {
|
|
|
+ throw BusinessRuntimeException.getInstance("车票不存在");
|
|
|
+ }
|
|
|
+ OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class).in(OrderDon::getUserId, userIdList).eq(OrderDon::getRelationId, relationId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).orderByDesc(OrderDon::getId).last("limit 1"));
|
|
|
+ if (orderDon == null) {
|
|
|
+ throw BusinessRuntimeException.getInstance("订单不存在");
|
|
|
+ }
|
|
|
+ SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.YOUTUBE_AFTER_SALES_TIME_KEY).last("limit 1"));
|
|
|
+ DateTime availableHandleTime = DateUtil.parse(sysConfig.getSysValue());
|
|
|
+ if (orderDon.getCreatedTime().after(availableHandleTime)) {
|
|
|
+ throw BusinessRuntimeException.getInstance("不可进行售后,请联系客服");
|
|
|
+ }
|
|
|
+ relationView.setNfOriOrderId(orderDon.getId());
|
|
|
+ return relationView;
|
|
|
+ }
|
|
|
+
|
|
|
private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user, List<Long> userIds) {
|
|
|
DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
|
|
|
.field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build());
|
|
|
@@ -2795,4 +3063,57 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ public OrderRefundDto getRefundInfo(GroupsRelationView netflixRelationView) {
|
|
|
+ OrderDon orderDon = orderDonMapper.selectById(netflixRelationView.getNfOriOrderId());
|
|
|
+ Long betweenDay = Long.valueOf(netflixRelationView.getReservedDays());
|
|
|
+ //未冻结时,使用车票时长
|
|
|
+ if (!netflixRelationView.getIsFrozen()) {
|
|
|
+ Date expiryTime = netflixRelationView.getExpiryTime();
|
|
|
+ if (expiryTime == null) {
|
|
|
+ //用订单时间
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ expiryTime = DateUtil.offsetMonth(orderDon.getCreatedTime(), sku.getMonths());
|
|
|
+ }
|
|
|
+ betweenDay= DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
|
|
|
+ }
|
|
|
+ GoodsDonSku oriTicketSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ //每天单价
|
|
|
+ BigDecimal dayPrice = oriTicketSku.getPrice().divide(BigDecimal.valueOf(oriTicketSku.getMonths() * 30), RoundingMode.DOWN);
|
|
|
+ //需要退款金额
|
|
|
+ BigDecimal totalRefundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay));
|
|
|
+ BigDecimal refundBalance = BigDecimal.ZERO;
|
|
|
+ BigDecimal refundMoney = BigDecimal.ZERO;
|
|
|
+ String outNo = StrUtil.EMPTY;
|
|
|
+ //订单金额为0 直接退款余额
|
|
|
+ if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
+ refundBalance = totalRefundMoney;
|
|
|
+ } else {
|
|
|
+ BigDecimal remainRefundBalanceMoney = null;
|
|
|
+ if (orderDon.getMoney().compareTo(totalRefundMoney) < 0) {
|
|
|
+ remainRefundBalanceMoney = totalRefundMoney.subtract(orderDon.getMoney());
|
|
|
+ refundMoney = orderDon.getMoney();
|
|
|
+ }
|
|
|
+ if (remainRefundBalanceMoney != null) {
|
|
|
+ refundBalance = refundBalance.add(remainRefundBalanceMoney);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ OrderRefundDto orderRefundDto = new OrderRefundDto();
|
|
|
+ orderRefundDto.setRefundBalance(refundBalance);
|
|
|
+ orderRefundDto.setRefundMoney(refundMoney);
|
|
|
+ return orderRefundDto;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getRefundType(BigDecimal refundMoney, BigDecimal refundBalance, OrderDon orderDon) {
|
|
|
+ String refundType;
|
|
|
+ if (refundMoney.compareTo(BigDecimal.ZERO) > 0 && refundBalance.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ refundType = "bxj";
|
|
|
+ } else if (refundMoney.compareTo(BigDecimal.ZERO) == 0 && refundBalance.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ refundType = "balance";
|
|
|
+ } else {
|
|
|
+ refundType = orderDon.getType().name();
|
|
|
+ }
|
|
|
+ return refundType;
|
|
|
+ }
|
|
|
}
|