package com.izouma.nineth.service; import com.izouma.nineth.TokenHistory; import com.izouma.nineth.domain.*; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.enums.AirDropType; import com.izouma.nineth.enums.CollectionType; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.*; import com.izouma.nineth.utils.JpaUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Page; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @Service @Slf4j public class AirDropService { @Autowired private AirDropRepo airDropRepo; @Autowired private CouponRepo couponRepo; @Autowired private UserCouponRepo userCouponRepo; @Autowired private CollectionRepo collectionRepo; @Autowired private UserRepo userRepo; @Lazy @Autowired private AssetService assetService; @Autowired private CollectionService collectionService; @Autowired private ShowroomService showroomService; @Autowired private TokenHistoryRepo tokenHistoryRepo; @Autowired private AssetRepo assetRepo; @Autowired private CollectionPrivilegeRepo collectionPrivilegeRepo; public Page all(PageQuery pageQuery) { return airDropRepo .findAll(JpaUtils.toSpecification(pageQuery, AirDrop.class), JpaUtils.toPageRequest(pageQuery)); } public AirDrop create(AirDrop record) { if (record.getTargets().isEmpty()) throw new BusinessException("空投对象不能为空"); if (record.getTargets().stream().mapToInt(DropTarget::getNum).sum() > 300) throw new BusinessException("空投数量不能超过300"); if (AirDropType.coupon == record.getType()) { Coupon coupon = couponRepo.findById(record.getCouponId()).orElseThrow(new BusinessException("兑换券不存在")); for (DropTarget target : record.getTargets()) { for (int i = 0; i < target.getNum(); i++) { UserCoupon userCoupon = new UserCoupon(); BeanUtils.copyProperties(coupon, userCoupon); userCoupon.setId(null); userCoupon.setCouponId(coupon.getId()); userCoupon.setUserId(target.getUserId()); userCouponRepo.save(userCoupon); } } } else { Collection collection = collectionRepo.findById(record.getCollectionId()) .orElseThrow(new BusinessException("藏品不存在")); if (collection.isSalable()) { throw new BusinessException("请先设置藏品为不可购买"); } if (!record.isIgnoreStockCheck() && collection.getStock() < record.getTargets().stream().mapToInt(DropTarget::getNum).sum()) { throw new BusinessException("藏品库存不足"); } List users = userRepo.findByIdInAndDelFalse(record.getTargets().stream() .map(DropTarget::getUserId).collect(Collectors.toList())); record.getTargets().parallelStream().forEach(target -> { User user = users.stream().filter(u -> u.getId().equals(target.getUserId())) .findFirst().orElse(null); if (user == null) return; try { for (int i = 0; i < target.getNum(); i++) { if (collection.getType() == CollectionType.BLIND_BOX) { BlindBoxItem winItem = collectionService.draw(target.getUserId(), collection.getId()); if (record.isSimulateOrder()) { assetService.createAsset(winItem, user, 0L, collection.getPrice(), "出售", winItem.getTotal() > 1 ? collectionService.getNextNumber(winItem.getCollectionId()) : null, collection.getHoldDays(), false); } else { //查看有无vip权限 CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo .findByCollectionId(record.getCollectionId()); if (ObjectUtils.isNotEmpty(collectionPrivilege)) { if (collectionPrivilege.isVip()) { //更新vip信息 userRepo.updateVipPurchase(user.getId(), 1); } } Asset asset = assetService.createAsset(winItem, user, null, null, "空投", winItem.getTotal() > 1 ? collectionService.getNextNumber(winItem.getCollectionId()) : null, collection.getHoldDays(), false); //铸造空投的t+0 if (record.isAuto()) { assetRepo.updateHoldDays(asset.getId(), 0); log.info("合成{},T+0", asset.getId()); } } } else { if (record.isSimulateOrder()) { assetService.createAsset(collection, user, 0L, collection.getPrice(), "出售", collectionService.getNextNumber(collection), false); } else { //查看有无vip权限 CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo .findByCollectionId(record.getCollectionId()); if (ObjectUtils.isNotEmpty(collectionPrivilege)) { if (collectionPrivilege.isVip()) { //更新vip信息 userRepo.updateVipPurchase(user.getId(), 1); } } Asset asset = assetService.createAsset(collection, user, null, null, "空投", collectionService.getNextNumber(collection), false); //创建展厅 if (collection.getType() == CollectionType.SHOWROOM) { asset.setOasisId(record.getOasisId()); showroomService.save(asset); } //铸造空投的t+0 if (record.isAuto()) { assetRepo.updateHoldDays(asset.getId(), 0); log.info("合成{},T+0", asset.getId()); } } } collectionService.decreaseStock(collection.getId(), 1); collectionService.increaseSale(collection.getId(), 1); } } catch (Exception e) { e.printStackTrace(); log.error("空投出错", e); } }); } return airDropRepo.save(record); } @Async public void asyncDrop(Long collectionId, Long userId, int num, LocalDateTime time) { drop(collectionId, userId, num, time); } public void drop(Long collectionId, Long userId, int num, LocalDateTime time) { Collection collection = collectionRepo.findById(collectionId) .orElseThrow(new BusinessException("藏品不存在")); User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); try { for (int i = 0; i < num; i++) { Asset asset; if (collection.getType() == CollectionType.BLIND_BOX) { BlindBoxItem winItem = collectionService.draw(userId, collection.getId()); asset = assetService.createAsset(winItem, user, 0L, collection.getPrice(), "出售", collectionService.getNextNumber(winItem), collection.getHoldDays(), true); } else { asset = assetService.createAsset(collection, user, 0L, collection.getPrice(), "出售", collectionService.getNextNumber(collection), true); } assetRepo.flush(); tokenHistoryRepo.flush(); asset.setCreatedAt(time.plusSeconds((long) (Math.random() * 120))); assetRepo.save(asset); for (TokenHistory tokenHistory : tokenHistoryRepo .findByTokenIdOrderByCreatedAtDesc(asset.getTokenId())) { tokenHistory.setCreatedAt(asset.getCreatedAt()); tokenHistoryRepo.save(tokenHistory); } log.info("空投成功{}/{} collectionId={}, userId={}", i + 1, num, collectionId, userId); } } catch (Exception e) { log.error("空投出错", e); } } public void drop(List collections, String phone, LocalDateTime time) { // List collections = collectionRepo.findAllById(collectionId); User user = userRepo.findByPhoneAndDelFalse(phone).orElseThrow(new BusinessException("用户不存在")); try { for (Collection collection : collections) { Asset asset; if (collection.getType() == CollectionType.BLIND_BOX) { BlindBoxItem winItem = collectionService.draw(user.getId(), collection.getId()); asset = assetService.createAsset(winItem, user, 0L, collection.getPrice(), "出售", collectionService.getNextNumber(winItem), collection.getHoldDays(), false); } else { asset = assetService.createAsset(collection, user, 0L, collection.getPrice(), "出售", collectionService.getNextNumber(collection), false); } assetRepo.flush(); tokenHistoryRepo.flush(); asset.setCreatedAt(time.plusSeconds((long) (Math.random() * 120))); assetRepo.save(asset); for (TokenHistory tokenHistory : tokenHistoryRepo .findByTokenIdOrderByCreatedAtDesc(asset.getTokenId())) { tokenHistory.setCreatedAt(asset.getCreatedAt()); tokenHistoryRepo.save(tokenHistory); } } } catch (Exception e) { log.error("空投出错", e); } } }