package com.izouma.nineth.service; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.google.common.hash.Hashing; import com.izouma.nineth.TokenHistory; import com.izouma.nineth.config.Constants; import com.izouma.nineth.config.GeneralProperties; import com.izouma.nineth.converter.LongArrayConverter; import com.izouma.nineth.domain.Collection; import com.izouma.nineth.domain.*; import com.izouma.nineth.dto.*; import com.izouma.nineth.enums.*; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.*; import com.izouma.nineth.utils.JpaUtils; import com.izouma.nineth.utils.SecurityUtils; import com.izouma.nineth.utils.TokenUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.BeanUtils; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.persistence.criteria.Predicate; import javax.transaction.Transactional; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @Service @AllArgsConstructor @Slf4j public class AssetService { private AssetRepo assetRepo; private UserRepo userRepo; private CollectionRepo collectionRepo; private OrderRepo orderRepo; private TokenHistoryRepo tokenHistoryRepo; private SysConfigService sysConfigService; private RocketMQTemplate rocketMQTemplate; private GeneralProperties generalProperties; private ShowroomRepo showroomRepo; private ShowCollectionRepo showCollectionRepo; private CollectionPrivilegeRepo collectionPrivilegeRepo; private PasswordEncoder passwordEncoder; private MintActivityRepo mintActivityRepo; private DestroyRecordRepo destroyRecordRepo; private AirDropService airDropService; private HCChainService hcChainService; private RockRecordService rockRecordService; private RockRecordRepo rockRecordRepo; private AssetLockRepo assetLockRepo; private UserBalanceService userBalanceService; private PhotoAssetRepo photoAssetRepo; private NumberSeqRepo numberSeqRepo; public Page all(PageQuery pageQuery) { Map query = pageQuery.getQuery(); Specification specification = JpaUtils.toSpecification(pageQuery, Asset.class); PageRequest pageRequest = JpaUtils.toPageRequest(pageQuery); if (query.containsKey("lock")) { LocalDateTime now = LocalDateTime.now(); query.remove("lock"); specification = specification.and((Specification) (root, criteriaQuery, criteriaBuilder) -> { List and = new ArrayList<>(); and.add(criteriaBuilder.greaterThan(root.get("lockTo"), now)); return criteriaBuilder.and(and.toArray(new Predicate[0])); }); } Page all = assetRepo.findAll(specification, pageRequest); // Map query = pageQuery.getQuery(); // if (query.containsKey("userId")) { // List orderId = orderRepo // .findAllByUserIdAndOpenedFalse(Convert.convert(Long.class, query.get("userId"))); // return all.map(asset -> { // if (orderId.contains(asset.getOrderId())) { // asset.setOpened(false); // } // return asset; // }); // } return new PageWrapper<>(all.getContent(), all.getPageable().getPageNumber(), all.getPageable().getPageSize(), all.getTotalElements()).toPage(); } public List userSummary(PageQuery pageQuery) { List assetDTOs = new ArrayList<>(); // 根据条件查询所有资产 List assets = assetRepo.findAll(JpaUtils.toSpecification(pageQuery, Asset.class)); if (CollectionUtils.isEmpty(assets)) { return assetDTOs; } // 取出资产中未开启盲盒数据 List blindBoxClosedAssets = assets.stream() .filter(asset -> !asset.isOpened() && CollectionType.BLIND_BOX.equals(asset.getType())) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(blindBoxClosedAssets)) { blindBoxClosedAssets.forEach(asset -> { assetDTOs.add(AssetDTO.create(Lists.newArrayList(asset))); }); // 移除资产中未开启盲盒数据 assets.removeAll(blindBoxClosedAssets); } // 取出资产中所有未设置prefixName的值 List prefixNameIsNullAssets = assets.stream() .filter(asset -> StringUtils.isBlank(asset.getPrefixName())) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(prefixNameIsNullAssets)) { prefixNameIsNullAssets.forEach(asset -> { assetDTOs.add(AssetDTO.create(Lists.newArrayList(asset))); }); assets.removeAll(prefixNameIsNullAssets); } if (CollectionUtils.isNotEmpty(assets)) { // 取出资产中所有prefixName List prefixNames = assets.stream() .map(Asset::getPrefixName) .distinct() .collect(Collectors.toList()); // 将资产中相同prefixName归类(除未开启盲盒和未设置prefixName) prefixNames.forEach(str -> { List collect = assets.stream() .filter(asset -> str.equals(asset.getPrefixName())) .collect(Collectors.toList()); assetDTOs.add(AssetDTO.create(collect)); }); } return assetDTOs; } public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number, boolean safeFlag) { if (collection.isMessNumber() && number != null) { number = getMessedNumber(collection.getId(), number, collection.getTotal()); } Asset asset = Asset.create(collection, user); asset.setTokenId(TokenUtils.genTokenId()); asset.setNumber(number); asset.setOasisId(collection.getOasisId()); asset.setOrderId(orderId); asset.setPrice(price); asset.setPrefixName(collection.getPrefixName()); asset.setTags(new HashSet<>()); if (collection.getTags() != null) { asset.getTags().addAll(collection.getTags()); } User fakeUser = null; if (safeFlag) { fakeUser = createFakeUser(); asset.setOwner(fakeUser.getNickname()); asset.setOwnerId(fakeUser.getId()); asset.setOwnerAvatar(fakeUser.getAvatar()); } assetRepo.saveAndFlush(asset); tokenHistoryRepo.save(TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(collection.getMinter()) .fromUserId(collection.getMinterId()) .fromAvatar(collection.getMinterAvatar()) .toUser((safeFlag ? fakeUser : user).getNickname()) .toUserId((safeFlag ? fakeUser : user).getId()) .toAvatar((safeFlag ? fakeUser : user).getAvatar()) .operation(type) .price(price) .companyId(asset.getCompanyId()) .build()); //绿洲石 rockRecordService.addRock(user.getId(), price, "购买"); rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); if (asset.getOasisId() != null & asset.getSource().equals(AssetSource.OFFICIAL)) { AirDrop airDrop = new AirDrop(); airDrop.setName("建筑空投展厅"); airDrop.setCollectionId(207012L); List userIds = new ArrayList<>(); userIds.add(user.getId()); List nums = new ArrayList<>(); nums.add(1L); airDrop.setType(AirDropType.asset); List dropTargets = new ArrayList<>(); DropTarget dropTarget = new DropTarget(); dropTarget.setNickname(user.getNickname()); dropTarget.setNum(1); dropTarget.setPhone(user.getPhone()); dropTarget.setUserId(user.getId()); dropTargets.add(dropTarget); airDrop.setTargets(dropTargets); airDrop.setUserIds(userIds); airDrop.setNum(nums); airDropService.create(airDrop); } return asset; } public Asset createAsset(PhotoAsset photoAsset, User user, Long orderId, BigDecimal price, String type, Integer number, boolean safeFlag) { Asset asset = Asset.create(photoAsset, user); asset.setTokenId(TokenUtils.genTokenId()); asset.setNumber(number); asset.setOrderId(orderId); asset.setPrice(price); asset.setPrefixName("星图"); asset.setTags(new HashSet<>()); User fakeUser = null; if (safeFlag) { fakeUser = createFakeUser(); asset.setOwner(fakeUser.getNickname()); asset.setOwnerId(fakeUser.getId()); asset.setOwnerAvatar(fakeUser.getAvatar()); } assetRepo.saveAndFlush(asset); tokenHistoryRepo.save(TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(photoAsset.getUserName()) .fromUserId(photoAsset.getUserId()) .fromAvatar(photoAsset.getUserAvatar()) .toUser((safeFlag ? fakeUser : user).getNickname()) .toUserId((safeFlag ? fakeUser : user).getId()) .toAvatar((safeFlag ? fakeUser : user).getAvatar()) .operation(type) .price(price) .companyId(asset.getCompanyId()) .build()); //绿洲石 // rockRecordService.addRock(user.getId(), price, "购买"); rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); return asset; } public Asset createAsset(DomainOrder domainOrder, User user, Long orderId, BigDecimal price, String type, Integer number, boolean safeFlag) { Asset asset = Asset.create(domainOrder, user); asset.setTokenId(TokenUtils.genTokenId()); asset.setNumber(number); asset.setOrderId(orderId); asset.setPrice(price); asset.setStatus(AssetStatus.PENDING); if (StringUtils.isNumeric(domainOrder.getPicName())) { if (domainOrder.getPicName().length() < 6) { asset.setPrefixName("RIDN" + domainOrder.getPicName().length()); } else { asset.setPrefixName("RIDN6"); } } else { Pattern p; p = Pattern.compile("[\u4E00-\u9FA5|\\!|\\,|\\。|\\(|\\)|\\《|\\》|\\“|\\”|\\?|\\:|\\;|\\【|\\】]"); Matcher m = p.matcher(domainOrder.getPicName()); if (m.find()) { asset.setPrefixName("RIDC"); } else { if (domainOrder.getPicName().length() < 6) { asset.setPrefixName("RID" + domainOrder.getPicName().length()); } else { asset.setPrefixName("RID"); } } } asset.setTags(new HashSet<>()); User fakeUser = null; if (safeFlag) { fakeUser = createFakeUser(); asset.setOwner(fakeUser.getNickname()); asset.setOwnerId(fakeUser.getId()); asset.setOwnerAvatar(fakeUser.getAvatar()); } assetRepo.saveAndFlush(asset); tokenHistoryRepo.save(TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(domainOrder.getUserName()) .fromUserId(domainOrder.getUserId()) .fromAvatar(domainOrder.getUserAvatar()) .toUser((safeFlag ? fakeUser : user).getNickname()) .toUserId((safeFlag ? fakeUser : user).getId()) .toAvatar((safeFlag ? fakeUser : user).getAvatar()) .operation(type) .price(price) .companyId(asset.getCompanyId()) .build()); //绿洲石 // rockRecordService.addRock(user.getId(), price, "购买"); rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); return asset; } public Asset createAsset(TradeAuction tradeAuction, User user, Long orderId, BigDecimal price, String type, Integer number, boolean safeFlag) { Asset asset = Asset.create(tradeAuction, user); asset.setTokenId(TokenUtils.genTokenId()); asset.setNumber(number); asset.setOrderId(orderId); asset.setPrice(price); asset.setPrefixName("易拍"); asset.setTags(new HashSet<>()); User fakeUser = null; if (safeFlag) { fakeUser = createFakeUser(); asset.setOwner(fakeUser.getNickname()); asset.setOwnerId(fakeUser.getId()); asset.setOwnerAvatar(fakeUser.getAvatar()); } assetRepo.saveAndFlush(asset); tokenHistoryRepo.save(TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(tradeAuction.getMinter()) .fromUserId(Long.valueOf(tradeAuction.getMinterId())) .fromAvatar(tradeAuction.getMinterAvatar()) .toUser((safeFlag ? fakeUser : user).getNickname()) .toUserId((safeFlag ? fakeUser : user).getId()) .toAvatar((safeFlag ? fakeUser : user).getAvatar()) .operation(type) .price(null) .companyId(asset.getCompanyId()) .build()); //绿洲石 // rockRecordService.addRock(user.getId(), price, "购买"); rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); return asset; } public synchronized int getMessedNumber(Long collectionId, int number, int total) { NumberSeq numberSeq = numberSeqRepo.findById(collectionId).orElse(null); if (numberSeq == null || numberSeq.getTotal() != total) { numberSeq = new NumberSeq(); numberSeq.setId(collectionId); numberSeq.setTotal(total); Map map = new HashMap<>(); for (int i = 0; i < total; i++) { map.put(i, Hashing.md5().hashString(collectionId + ":" + i, StandardCharsets.UTF_8).asInt()); } numberSeq.setNumbers(map.entrySet().stream() .sorted(Map.Entry.comparingByValue()) .map(Map.Entry::getKey) .collect(Collectors.toList())); numberSeqRepo.save(numberSeq); } return numberSeq.getNumbers().get(number); } public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type, Integer number, Integer holdDays, boolean safeFlag) { Collection blindBox = collectionRepo.findDetailById(winItem.getBlindBoxId()) .orElseThrow(new BusinessException("盲盒不存在")); Collection collection = collectionRepo.findDetailById(winItem.getCollectionId()) .orElseThrow(new BusinessException("藏品不存在")); if (collection.isMessNumber() && number != null) { number = getMessedNumber(collection.getId(), number, collection.getTotal()); } winItem.setCollection(collection); Asset asset = Asset.create(winItem, user, holdDays); if (collection.getType().equals(CollectionType.DOMAIN)) { asset.setType(CollectionType.DOMAIN); } asset.setTokenId(TokenUtils.genTokenId()); asset.setNumber(number); asset.setOasisId(winItem.getOasisId()); asset.setOrderId(orderId); asset.setPrice(price); asset.setPrefixName(collection.getPrefixName()); asset.setEmpower(collection.getEmpower()); asset.setTags(new HashSet<>()); if (blindBox.getTags() != null) { asset.getTags().addAll(blindBox.getTags()); } if (collection.getTags() != null) { asset.getTags().addAll(collection.getTags()); } User fakeUser = null; if (safeFlag) { fakeUser = createFakeUser(); asset.setOwner(fakeUser.getNickname()); asset.setOwnerId(fakeUser.getId()); asset.setOwnerAvatar(fakeUser.getAvatar()); } assetRepo.saveAndFlush(asset); tokenHistoryRepo.save(TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(winItem.getMinter()) .fromUserId(winItem.getMinterId()) .fromAvatar(winItem.getMinterAvatar()) .toUser((safeFlag ? fakeUser : user).getNickname()) .toUserId((safeFlag ? fakeUser : user).getId()) .toAvatar((safeFlag ? fakeUser : user).getAvatar()) .operation(type) .price(price) .companyId(asset.getCompanyId()) .build()); //绿洲石 rockRecordService.addRock(user.getId(), price, "购买"); rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); return asset; } public void publicShow(Long id) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } if (asset.getLockTo() != null && asset.getLockTo().isAfter(LocalDateTime.now())) { throw new BusinessException("已锁仓,不能上架展示"); } if (asset.isPublicShow()) { return; } if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可展示"); } User owner = asset.isSafeFlag() ? userRepo.findById(asset.getOwnerId()).orElseThrow(new BusinessException("用户不存在")) : userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在")); Collection collection = Collection.builder() .name(asset.getName()) .pic(asset.getPic()) .minter(asset.getMinter()) .minterId(asset.getMinterId()) .minterAvatar(asset.getMinterAvatar()) .owner(owner.getNickname()) .oasisId(asset.getOasisId()) .ownerId(owner.getId()) .ownerAvatar(owner.getAvatar()) .detail(asset.getDetail()) .type(CollectionType.DEFAULT) .source(CollectionSource.TRANSFER) .sale(0) .stock(1) .total(1) .onShelf(true) .salable(false) .price(BigDecimal.valueOf(0)) .properties(asset.getProperties()) .canResale(asset.isCanResale()) .royalties(asset.getRoyalties()) .serviceCharge(asset.getServiceCharge()) .assetId(id) .number(asset.getNumber()) .tags(new HashSet<>()) .prefixName(asset.getPrefixName()) .companyId(asset.getCompanyId()) .build(); if (asset.getTags() != null) { collection.getTags().addAll(asset.getTags()); } if (asset.getType().equals(CollectionType.PICTURE)) { collection.setType(CollectionType.PICTURE); } if (asset.getType().equals(CollectionType.DOMAIN)) { collection.setType(CollectionType.DOMAIN); } collectionRepo.save(collection); asset.setPublicShow(true); asset.setPublicCollectionId(collection.getId()); assetRepo.saveAndFlush(asset); } public synchronized void consignment(Long id, BigDecimal price, String tradeCode, boolean safeFlag) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); String mapString = sysConfigService.getString("collection_price"); if (StringUtils.isNotBlank(mapString)) { JSONObject json = JSONObject.parseObject(mapString); String assetName = asset.getName(); json.forEach((k, v) -> { if (assetName.contains(k)) { Map map = (Map) v; BigDecimal max = BigDecimal.valueOf(Double.parseDouble(map.get("maxPrice").toString())); BigDecimal min = BigDecimal.valueOf(Double.parseDouble(map.get("minPrice").toString())); if (price.compareTo(max) > 0) { throw new BusinessException("已经超过藏品最高限价" + max + "元"); } if (price.compareTo(min) < 0) { throw new BusinessException("低于藏品最低限价" + min + "元"); } } }); } if (Objects.nonNull(asset.getType()) && asset.getType().equals(CollectionType.SHOWROOM)) { throw new BusinessException("展厅类型的藏品不能上架"); } if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } if (asset.getType().equals(CollectionType.PICTURE)) { throw new BusinessException("星图藏品不可寄售"); } if (!sysConfigService.getBoolean("domain_transfer")) { throw new BusinessException("域名暂不可以寄售"); } if (asset.getLockTo() != null && asset.getLockTo().isAfter(LocalDateTime.now())) { throw new BusinessException("已锁仓,不能寄售"); } List bannedAssets = Arrays.asList(sysConfigService.getString("older_collections").split(",").clone()); bannedAssets.forEach(name -> { if (asset.getName().contains(name)) { throw new BusinessException("编年史藏品无法寄售"); } }); int holdDays = 0; if (!asset.getType().equals(CollectionType.DOMAIN)) { if (asset.getSource() == AssetSource.GIFT) { LocalDateTime localDateTime = asset.getCreatedAt(); LocalDateTime gift_change_time = LocalDateTime .parse(sysConfigService.getString("gift_change_time"), DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss")); if (localDateTime.compareTo(gift_change_time) < 0) { holdDays = 20; } else { holdDays = sysConfigService.getInt("gift_days"); } } else { if (ObjectUtils.isEmpty(asset.getHoldDays())) { holdDays = sysConfigService.getInt("hold_days"); } else { holdDays = asset.getHoldDays(); } } } else { if (!ObjectUtils.isEmpty(asset.getHoldDays())) { holdDays = asset.getHoldDays(); } } if (holdDays == 0 && AssetSource.OFFICIAL.equals(asset.getSource())) { BigDecimal officialConsignment = sysConfigService.getBigDecimal("OFFICIAL_CONSIGNMENT"); //天转小时 int hour = officialConsignment.multiply(new BigDecimal("24")).intValue(); if (ChronoUnit.HOURS.between(asset.getCreatedAt(), LocalDateTime.now()) < hour) { throw new BusinessException("需持有满" + hour + "小时后才能寄售上架"); } } if (ChronoUnit.DAYS.between(asset.getCreatedAt(), LocalDateTime.now()) < holdDays) { throw new BusinessException("需持有满" + holdDays + "天才能寄售上架"); } User owner; if (safeFlag && !asset.isSafeFlag()) { owner = createFakeUser(); asset.setOwner(owner.getNickname()); asset.setOwnerId(owner.getId()); asset.setOwnerAvatar(owner.getAvatar()); asset.setSafeFlag(true); tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(asset.getTokenId()).stream() .filter(t -> t.getToUserId().equals(asset.getUserId())).findFirst() .ifPresent(tokenHistory -> { tokenHistory.setToUserId(owner.getId()); tokenHistory.setToUser(owner.getNickname()); tokenHistory.setToAvatar(owner.getAvatar()); tokenHistoryRepo.save(tokenHistory); }); } else { owner = asset.isSafeFlag() ? userRepo.findById(asset.getOwnerId()).orElseThrow(new BusinessException("用户不存在")) : userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在")); } if (!passwordEncoder.matches(tradeCode, userRepo.findTradeCode(asset.getUserId()))) { throw new BusinessException("交易密码错误"); } // if (StringUtils.isBlank(owner.getSettleAccountId())) { // throw new BusinessException("请先绑定银行卡"); // } if (asset.isConsignment()) { throw new BusinessException("已寄售,请勿重新操作"); } if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可寄售"); } if (asset.isPublicShow()) { cancelPublic(asset); } //寄售中的展厅需要先删除展厅 if (CollectionType.SHOWROOM.equals(asset.getType())) { if (showroomRepo.findByAssetId(id).isPresent()) { throw new BusinessException("请先删除展厅"); } } Collection collection = Collection.builder() .name(asset.getName()) .pic(asset.getPic()) .minter(asset.getMinter()) .minterId(asset.getMinterId()) .minterAvatar(asset.getMinterAvatar()) .owner(owner.getNickname()) .ownerId(owner.getId()) .oasisId(asset.getOasisId()) .ownerAvatar(owner.getAvatar()) .detail(asset.getDetail()) .type(CollectionType.DEFAULT) .source(CollectionSource.TRANSFER) .sale(0) .stock(1) .total(1) .onShelf(true) .salable(true) .price(price) .properties(asset.getProperties()) .canResale(asset.isCanResale()) .royalties(asset.getRoyalties()) .serviceCharge(asset.getServiceCharge()) .assetId(id) .number(asset.getNumber()) .tags(new HashSet<>()) .prefixName(asset.getPrefixName()) .companyId(asset.getCompanyId()) .build(); if (asset.getType().equals(CollectionType.DOMAIN)) { collection.setType(CollectionType.DOMAIN); } if (asset.getTags() != null) { collection.getTags().addAll(asset.getTags()); } collectionRepo.save(collection); asset.setPublicShow(true); asset.setConsignment(true); asset.setPublicCollectionId(collection.getId()); asset.setSellPrice(price); assetRepo.saveAndFlush(asset); } public Asset cancelConsignmentAndStore(Long id) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可寄售"); } if (asset.getPublicCollectionId() != null) { List orders = orderRepo.findByCollectionId(asset.getPublicCollectionId()); if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) { throw new BusinessException("已有订单不可取消"); } collectionRepo.findById(asset.getPublicCollectionId()) .ifPresent(collection -> { collection.setSalable(false); collection.setOnShelf(false); collectionRepo.save(collection); }); } asset.setConsignment(false); asset.setPublicShow(false); asset.setStatus(AssetStatus.DESTROYING); return assetRepo.saveAndFlush(asset); } public void batchCancelConsignment(String search) { List onShelf = assetRepo.findOnShelfByNameLike("%" + search + "%"); onShelf.forEach(this::cancelConsignmentBySystem); } public void cancelConsignment(Long id) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } cancelConsignment(asset); } public void cancelConsignment(Asset asset) { if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } if (asset.getPublicCollectionId() != null) { List orders = orderRepo.findByCollectionId(asset.getPublicCollectionId()); if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) { throw new BusinessException("已有订单不可取消"); } collectionRepo.findById(asset.getPublicCollectionId()) .ifPresent(collection -> { collection.setSalable(false); collectionRepo.save(collection); }); } asset.setConsignment(false); assetRepo.saveAndFlush(asset); } public void cancelPublic(Long id) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } cancelPublic(asset); } public void cancelPublic(Asset asset) { if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) { throw new BusinessException("此藏品不属于你"); } if (!asset.isPublicShow()) { return; } if (asset.isConsignment()) { cancelConsignment(asset); } Collection collection = collectionRepo.findById(asset.getPublicCollectionId()) .orElseThrow(new BusinessException("无展示记录")); collectionRepo.delete(collection); // 如果展厅有此藏品 showCollectionRepo.deleteAllByCollectionId(asset.getPublicCollectionId()); asset.setPublicShow(false); asset.setPublicCollectionId(null); assetRepo.saveAndFlush(asset); } public void usePrivilege(Long assetId, Long privilegeId) { Asset asset = assetRepo.findById(assetId).orElseThrow(new BusinessException("无记录")); asset.getPrivileges().stream().filter(p -> p.getId().equals(privilegeId)).forEach(p -> { if (!p.getName().equals("铸造")) { p.setOpened(true); p.setOpenTime(LocalDateTime.now()); p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId()); } }); assetRepo.saveAndFlush(asset); } public void transfer(Asset asset, BigDecimal price, User toUser, TransferReason reason, Long orderId) { transfer(asset, price, toUser, reason, orderId, false, asset.getTags()); } private User createFakeUser() { String name = "0x" + RandomStringUtils.randomAlphabetic(8); return userRepo.save(User.builder() .username(name) .nickname(name) .avatar(Constants.DEFAULT_AVATAR) .isPublicShow(true) .build()); } public void transfer(Asset asset, BigDecimal price, User toUser, TransferReason reason, Long orderId, boolean safeFlag, Set tags) { Objects.requireNonNull(asset, "原藏品不能为空"); Objects.requireNonNull(toUser, "转让人不能为空"); Objects.requireNonNull(reason, "转让原因不能为空"); User newOwner = toUser; if (safeFlag) { newOwner = createFakeUser(); } Asset newAsset = new Asset(); BeanUtils.copyProperties(asset, newAsset); newAsset.setId(null); newAsset.setUserId(toUser.getId()); newAsset.setOwner(newOwner.getNickname()); newAsset.setOwnerId(newOwner.getId()); newAsset.setOwnerAvatar(newOwner.getAvatar()); newAsset.setPublicShow(false); newAsset.setConsignment(false); newAsset.setPublicCollectionId(null); newAsset.setTags(new HashSet<>(tags)); asset.setTags(new HashSet<>()); newAsset.setStatus(AssetStatus.NORMAL); newAsset.setPrice(price); newAsset.setSellPrice(null); newAsset.setOrderId(orderId); newAsset.setOasisId(asset.getOasisId()); newAsset.setFromAssetId(asset.getId()); newAsset.setType(CollectionType.DEFAULT); if (asset.getType() == CollectionType.DOMAIN) { newAsset.setType(CollectionType.DOMAIN); } newAsset.setSource(TransferReason.GIFT == reason ? AssetSource.GIFT : AssetSource.TRANSFER); newAsset.setSafeFlag(safeFlag); newAsset.setHoldDays(asset.getOldHoldDays()); if (asset.getType().equals(CollectionType.PICTURE)) { newAsset.setType(CollectionType.PICTURE); newAsset.setHoldDays(0); } Long savedId = assetRepo.saveAndFlush(newAsset).getId(); if (asset.getType().equals(CollectionType.PICTURE)) { newAsset.setType(CollectionType.PICTURE); PhotoAsset photoAsset = photoAssetRepo.findFirstByCreateAssetId(asset.getId()); photoAsset.setGifted(true); photoAsset.setOwnerId(toUser.getId()); photoAsset.setCreateAssetId(savedId); photoAssetRepo.save(photoAsset); } TokenHistory tokenHistory = TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(asset.getOwner()) .fromUserId(asset.getOwnerId()) .fromAvatar(asset.getOwnerAvatar()) .toUser(newOwner.getNickname()) .toUserId(newOwner.getId()) .toAvatar(newOwner.getAvatar()) .operation(reason.getDescription()) .price(TransferReason.GIFT == reason ? null : price) .companyId(asset.getCompanyId()) .build(); tokenHistoryRepo.save(tokenHistory); //购买者加绿洲石 if (TransferReason.TRANSFER.equals(reason) || TransferReason.AUCTION.equals(reason)) { rockRecordService.addRock(newOwner.getId(), price, "购买"); } asset.setPublicShow(false); asset.setConsignment(false); asset.setPublicCollectionId(null); switch (reason) { case GIFT: asset.setStatus(AssetStatus.GIFTED); break; case AUCTION: asset.setStatus(AssetStatus.AUCTIONED); break; case TRANSFER: asset.setStatus(AssetStatus.TRANSFERRED); } asset.setOwner(newOwner.getNickname()); asset.setOwnerId(newOwner.getId()); asset.setOwnerAvatar(newOwner.getAvatar()); assetRepo.saveAndFlush(asset); //vip权限转让 CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo.findByCollectionId(asset.getCollectionId()); if (ObjectUtils.isNotEmpty(collectionPrivilege)) { if (collectionPrivilege.isVip()) { //更新vip信息 userRepo.updateVipPurchase(toUser.getId(), 1); userRepo.updateVipPurchase(asset.getUserId(), 0); } } } public List tokenHistory(String tokenId, Long assetId) { if (tokenId == null) { if (assetId == null) return new ArrayList<>(); tokenId = assetRepo.findById(assetId).map(Asset::getTokenId).orElse(null); } if (tokenId == null) return new ArrayList<>(); return tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(tokenId); } public Page userHistory(Long userId, Long toUserId, Long fromUserId, Pageable pageable) { Page page; if (ObjectUtils.isNotEmpty(toUserId)) { page = tokenHistoryRepo.userHistoryTo(userId, toUserId, pageable); } else if (ObjectUtils.isNotEmpty(fromUserId)) { page = tokenHistoryRepo.userHistoryFrom(userId, fromUserId, pageable); } else { page = tokenHistoryRepo.userHistory(userId, pageable); } Set tokenIds = page.stream().map(TokenHistory::getTokenId).collect(Collectors.toSet()); List assets = tokenIds.isEmpty() ? new ArrayList<>() : assetRepo.findByTokenIdIn(tokenIds); return page.map(tokenHistory -> { UserHistory userHistory = new UserHistory(); BeanUtils.copyProperties(tokenHistory, userHistory); Optional asset = assets.stream().filter(a -> a.getTokenId().equals(tokenHistory.getTokenId())) .findAny(); userHistory.setAssetName(asset.map(Asset::getName).orElse(null)); userHistory.setPic(asset.map(Asset::getPic).orElse(new ArrayList<>())); switch (tokenHistory.getOperation()) { case "出售": case "转让": userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出"); break; case "转赠": userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送"); break; default: userHistory.setDescription(tokenHistory.getOperation()); } return userHistory; }); } public Page userHistory(Long userId, PageQuery pageQuery) { Page page = tokenHistoryRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> { List and = JpaUtils .toPredicates(pageQuery, TokenHistory.class, root, criteriaQuery, criteriaBuilder); Map query = pageQuery.getQuery(); if (ObjectUtils.isEmpty(query.get("toUserId")) && ObjectUtils.isEmpty(query.get("fromUserId"))) { and.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("toUserId"), userId), criteriaBuilder .equal(root.get("fromUserId"), userId))); } else { if (ObjectUtils.isNotEmpty(query.get("toUserId"))) { and.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("toUserId"), userId))); } else { and.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("fromUserId"), userId))); } } return criteriaBuilder.and(and.toArray(new Predicate[0])); }), JpaUtils.toPageRequest(pageQuery)); Set tokenIds = page.stream().map(TokenHistory::getTokenId).collect(Collectors.toSet()); List assets = tokenIds.isEmpty() ? new ArrayList<>() : assetRepo.findByTokenIdIn(tokenIds); return page.map(tokenHistory -> { UserHistory userHistory = new UserHistory(); BeanUtils.copyProperties(tokenHistory, userHistory); Optional asset = assets.stream().filter(a -> a.getTokenId().equals(tokenHistory.getTokenId())) .findAny(); userHistory.setAssetName(asset.map(Asset::getName).orElse(null)); userHistory.setPic(asset.map(Asset::getPic).orElse(new ArrayList<>())); switch (tokenHistory.getOperation()) { case "出售": case "转让": userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出"); break; case "转赠": userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送"); break; default: userHistory.setDescription(tokenHistory.getOperation()); } return userHistory; }); } public String mint(LocalDateTime time) { if (time == null) { time = LocalDateTime.now(); } for (Asset asset : assetRepo.toMint(time)) { rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId()); } return "ok"; } @Cacheable(value = "userStat", key = "#userId") public Map breakdown(Long userId) { // List page = tokenHistoryRepo.userHistory(userId); // BigDecimal sale = page.stream() // .filter(th -> th.getFromUserId().equals(userId) && ObjectUtils.isNotEmpty(th.getPrice())) // .map(TokenHistory::getPrice) // .reduce(BigDecimal.ZERO, BigDecimal::add); // BigDecimal buy = page.stream() // .filter(th -> th.getToUserId().equals(userId) && ObjectUtils.isNotEmpty(th.getPrice())) // .map(TokenHistory::getPrice) // .reduce(BigDecimal.ZERO, BigDecimal::add); Map map = new HashMap<>(); map.put("sale", tokenHistoryRepo.userSale(userId)); map.put("buy", rockRecordService.getRock(userId).getRecord()); return map; } public void transferCDN() throws ExecutionException, InterruptedException { ForkJoinPool customThreadPool = new ForkJoinPool(100); customThreadPool.submit(() -> { collectionRepo.selectResource().parallelStream().forEach(list -> { for (int i = 0; i < list.size(); i++) { list.set(i, replaceCDN(list.get(i))); } collectionRepo.updateCDN(Long.parseLong(list.get(0)), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5)); }); assetRepo.selectResource().parallelStream().forEach(list -> { for (int i = 0; i < list.size(); i++) { list.set(i, replaceCDN(list.get(i))); } assetRepo.updateCDN(Long.parseLong(list.get(0)), list.get(1), list.get(2), list.get(3), list.get(4), list.get(5)); }); }).get(); } public String replaceCDN(String url) { if (url == null) return null; return url.replaceAll("https://raex-meta\\.oss-cn-shenzhen\\.aliyuncs\\.com", "https://cdn.raex.vip"); } // @Scheduled(cron = "0 0 0/1 * * ?") // public void offTheShelf() { // LocalDateTime lastTime = LocalDateTime.now().minusHours(120); // Set assetIds = collectionRepo // .findResaleCollectionPriceOver20K(BigDecimal // .valueOf(20000L), CollectionSource.TRANSFER, lastTime, true); // assetIds.forEach(this::cancelConsignmentBySystem); // } @Scheduled(cron = "0 0 0/1 * * ?") public void offTheShelfAll() { LocalDateTime lastTime = LocalDateTime.now().minusDays(15); LocalDateTime newRuleStartTime = LocalDateTime.of(2022, 12, 9, 17, 0, 0); Set assetIds = collectionRepo .findResaleCollectionOverTime(lastTime, newRuleStartTime); LocalDateTime newRuleLastTime = LocalDateTime.now().minusDays(30); assetIds.addAll(collectionRepo .findResaleCollectionOverTimeV2(newRuleLastTime, newRuleStartTime)); assetIds.forEach(this::cancelConsignmentBySystem); } public void cancelConsignmentBySystem(Long id) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); cancelConsignmentBySystem(asset); } public void cancelConsignmentBySystem(Asset asset) { try { if (asset.getPublicCollectionId() != null) { List orders = orderRepo.findByCollectionId(asset.getPublicCollectionId()); if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) { throw new BusinessException("已有订单不可取消"); } collectionRepo.findById(asset.getPublicCollectionId()) .ifPresent(collection -> { collection.setSalable(false); collection.setOnShelf(false); collectionRepo.save(collection); }); } asset.setConsignment(false); asset.setPublicShow(false); assetRepo.saveAndFlush(asset); } catch (Exception e) { log.info("自动下架报错,assetId:" + asset.getId()); } } // @Cacheable(cacheNames = "fmaa", key = "#userId+'#'+#mintActivityId+'#'+#pageable.hashCode()") public PageWrapper findMintActivityAssetsWrap(Long userId, Long mintActivityId, Long companyId, Pageable pageable) { return PageWrapper.of(findMintActivityAssets(userId, mintActivityId, companyId, pageable)); } public Page findMintActivityAssets(Long userId, Long mintActivityId, Long companyId, Pageable pageable) { MintActivity mintActivity = mintActivityRepo.findById(mintActivityId).orElse(null); if (mintActivity == null) return new PageImpl<>(Collections.emptyList()); return findMintActivityAssetsCommon(userId, companyId, new CommonMatchDTO(mintActivity.getRule(), mintActivity.isAudit(), mintActivity.getCollectionName()), pageable); } public Page findMintActivityAssetsCommon(Long userId, Long companyId, CommonMatchDTO commonMatchDTO, Pageable pageable) { if (!commonMatchDTO.isAudit()) { Set tags = commonMatchDTO.getRule().getTags(); if (tags.isEmpty()) return new PageImpl<>(Collections.emptyList()); return assetRepo.findAll((Specification) (root, query, criteriaBuilder) -> query.distinct(true).where( // where userId=some id criteriaBuilder.equal(root.get("userId"), userId), // and (lockTo is null or (lockTo is not null and lockTo < now)) criteriaBuilder.or(criteriaBuilder.isNull(root.get("lockTo")), criteriaBuilder.and(criteriaBuilder.isNotNull(root.get("lockTo")), criteriaBuilder.lessThan(root.get("lockTo"), LocalDateTime.now()))), // and status = 'NORMAL' criteriaBuilder.equal(root.get("status"), AssetStatus.NORMAL), criteriaBuilder.equal(root.get("consignment"), false), // and has some tagId root.join("tags").get("id").in(tags.stream().map(Tag::getId).toArray())) .getRestriction(), pageable); } else { return assetRepo .findByUserIdAndStatusAndCompanyIdAndNameLikeAndConsignment(userId, AssetStatus.NORMAL, companyId, "%" + commonMatchDTO.getCollectionName() + "%", pageable, false); } } public void destroy(Long id, Long userId, String tradeCode, OperationSource source) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(userId)) { throw new BusinessException("此藏品不属于你"); } if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可销毁"); } if (asset.isPublicShow()) { throw new BusinessException("请先取消公开展示"); // cancelPublic(asset); } User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); if (StringUtils.isEmpty(user.getTradeCode())) { throw new BusinessException("未设置交易密码"); } if (!passwordEncoder.matches(tradeCode, user.getTradeCode())) { throw new BusinessException("交易密码错误"); } User toUser = userRepo.findById(Constants.BLACK_HOLE_USER_ID).orElseThrow(new BusinessException("无记录")); TokenHistory tokenHistory = TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(asset.getOwner()) .fromUserId(asset.getOwnerId()) .fromAvatar(asset.getOwnerAvatar()) .toUser(toUser.getNickname()) .toUserId(toUser.getId()) .toAvatar(toUser.getAvatar()) .operation(TransferReason.DESTROY.getDescription()) .price(null) .companyId(asset.getCompanyId()) .build(); tokenHistoryRepo.save(tokenHistory); asset.setPublicShow(false); asset.setConsignment(false); asset.setPublicCollectionId(null); asset.setStatus(AssetStatus.DESTROYED); asset.setOwner(toUser.getNickname()); asset.setOwnerId(toUser.getId()); asset.setOwnerAvatar(toUser.getAvatar()); assetRepo.saveAndFlush(asset); //积分记录 destroyRecordRepo.save(DestroyRecord.builder() .userId(userId) .assetId(asset.getId()) .name(asset.getName()) .pic(asset.getPic().get(0).getUrl()) .record(1) .type(RecordType.OBTAIN) .companyId(asset.getCompanyId()) .source(source) .build()); //加积分 userRepo.addDestroyPoint(userId, 1); } @Transactional public void metaDestroyWithoutTradeCode(MetaDestroyParam metaDestroyParam, Long userId, OperationSource source) { List ids = metaDestroyParam.getIds(); String remark = metaDestroyParam.getRemark(); if (CollectionUtils.isEmpty(ids)) { throw new BusinessException("要销毁的藏品id为空"); } ids.forEach(id -> { destroyWithoutTradeCode(id, userId, source, remark); }); } public void destroyWithoutTradeCode(Long id, Long userId, OperationSource source, String remark) { Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (!asset.getUserId().equals(userId)) { throw new BusinessException("此藏品不属于该用户"); } if (OperationSource.META.equals(source)) { if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可销毁"); } } else { if (asset.getStatus() != AssetStatus.DESTROYING) { throw new BusinessException("当前状态不可销毁"); } } if (asset.isPublicShow()) { throw new BusinessException("请先取消公开展示"); // cancelPublic(asset); } User toUser = userRepo.findById(Constants.BLACK_HOLE_USER_ID).orElseThrow(new BusinessException("无记录")); TokenHistory tokenHistory = TokenHistory.builder() .tokenId(asset.getTokenId()) .fromUser(asset.getOwner()) .fromUserId(asset.getOwnerId()) .fromAvatar(asset.getOwnerAvatar()) .toUser(toUser.getNickname()) .toUserId(toUser.getId()) .toAvatar(toUser.getAvatar()) .operation(TransferReason.DESTROY.getDescription()) .price(null) .companyId(asset.getCompanyId()) .build(); tokenHistoryRepo.save(tokenHistory); asset.setPublicShow(false); asset.setConsignment(false); asset.setPublicCollectionId(null); asset.setStatus(AssetStatus.DESTROYED); asset.setOwner(toUser.getNickname()); asset.setOwnerId(toUser.getId()); asset.setOwnerAvatar(toUser.getAvatar()); assetRepo.saveAndFlush(asset); //积分记录 DestroyRecord destroyRecord = DestroyRecord.builder() .userId(userId) .assetId(asset.getId()) .name(asset.getName()) .record(1) .type(RecordType.OBTAIN) .companyId(asset.getCompanyId()) .source(source) .remark(remark) .build(); destroyRecord .setPic("video/mp4".equals(asset.getPic().get(0).getType()) ? asset.getPic().get(0).getThumb() : asset .getPic().get(0).getUrl()); destroyRecordRepo.save(destroyRecord); //加积分 userRepo.addDestroyPoint(userId, 1); } public double getRoyalties(Long minterId, double royalties, Long userId) { if (royalties == 2) { return 2; } LongArrayConverter converter = new LongArrayConverter(); String discountMinter = sysConfigService.getString("discount_minter"); List minterIds = converter.convertToEntityAttribute(discountMinter); if (minterIds.contains(minterId)) { String discountCollection = sysConfigService.getString("discount_collection"); List collectionIds = converter.convertToEntityAttribute(discountCollection); Long assetId = assetRepo.findDiscount(userId, collectionIds); if (ObjectUtils.isNotEmpty(assetId)) { return 2; } } return royalties; } public double getServicecharge(double servicecharge, Long userId) { // if (servicecharge == 3) { // return 3; // } LongArrayConverter converter = new LongArrayConverter(); // String discountMinter = sysConfigService.getString("discount_minter"); // List minterIds = converter.convertToEntityAttribute(discountMinter); // if (minterIds.contains(minterId)) { String discountCollection = sysConfigService.getString("discount_charge"); List collectionIds = converter.convertToEntityAttribute(discountCollection); Long assetId = assetRepo.findDiscount(userId, collectionIds); if (ObjectUtils.isNotEmpty(assetId)) { return 3; } // } return servicecharge; } public double getDomainServiceCharge(Long userId) { // if (servicecharge == 3) { // return 3; // } // LongArrayConverter converter = new LongArrayConverter(); // String discountMinter = sysConfigService.getString("discount_minter"); // List minterIds = converter.convertToEntityAttribute(discountMinter); // if (minterIds.contains(minterId)) { String discountCollection = sysConfigService.getString("domain_discount"); JSONObject json = JSONObject.parseObject(discountCollection); Set keys = json.keySet(); List collectionIds = keys.stream().map(Long::parseLong).collect(Collectors.toList()); Set holdCollections = assetRepo.findDiscounts(userId, collectionIds); double result = sysConfigService.getBigDecimal("domain_service_charge").doubleValue(); if (holdCollections.size() > 0) { for (Long id : holdCollections) { double discount = json.getDouble(id.toString()); if (discount < result) { result = discount; } } } // } return result; } @Async public void hcChain() throws ExecutionException, InterruptedException { new ForkJoinPool(1000).submit(() -> { AtomicInteger num = new AtomicInteger(); assetRepo.findByStatus(AssetStatus.NORMAL).parallelStream() .forEach(asset -> { if (asset.getHcTxHash() == null) { User user = userRepo.findById(asset.getUserId()).orElse(null); if (user != null) { if (user.getHcChainAddress() == null) { user.setHcChainAddress(hcChainService.createAccount(asset.getUserId())); } NFT nft = hcChainService.mint(user.getHcChainAddress(), asset.getTokenId()); asset.setHcTokenId(nft.getTokenId()); asset.setHcTxHash(nft.getTxHash()); asset.setGasUsed(nft.getGasUsed()); assetRepo.saveAndFlush(asset); } } log.info("hcChain:" + num.getAndIncrement()); }); }).get(); } public void lockAsset(Long userId, Long assetId, Duration duration) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在")); Asset asset = assetRepo.findById(assetId).orElseThrow(new BusinessException("藏品不存在")); if (!asset.getUserId().equals(userId)) { throw new BusinessException("无权限"); } if (asset.getLockTo() != null && asset.getLockTo().isAfter(LocalDateTime.now())) { throw new BusinessException("已是锁仓状态"); } if (asset.getType() == CollectionType.SHOWROOM) { throw new BusinessException("展厅不可锁定"); } if (asset.getStatus() != AssetStatus.NORMAL) { throw new BusinessException("当前状态不可锁定"); } if (asset.isPublicShow() || asset.isConsignment()) { throw new BusinessException("请先取消展示和寄售"); } if (duration.compareTo(Duration.parse("P1D")) < 0) { throw new BusinessException("最小锁定1天"); } asset.setLockAt(LocalDateTime.now()); asset.setLockTo(asset.getLockAt().plus(duration)); assetRepo.saveAndFlush(asset); assetLockRepo.save(AssetLock.builder() .userId(userId) .phone(user.getPhone()) .nickname(user.getNickname()) .assetId(assetId) .name(asset.getName()) .number(asset.getNumber()) .lockAt(asset.getLockAt()) .lockTo(asset.getLockTo()) .duration(duration) .build()); } public List transactionTopTen() { LocalDateTime localDateTime = LocalDateTime.now().plusDays(-7); List> map = orderRepo.transactionTopTen(localDateTime); JSONArray jsonArray = new JSONArray(); if (CollectionUtil.isEmpty(map)) { return null; } jsonArray.addAll(map); List transactionTopTenDTOS = jsonArray.toJavaList(TransactionTopTenDTO.class); if (CollectionUtil.isEmpty(transactionTopTenDTOS)) { return null; } transactionTopTenDTOS.forEach(transactionTopTenDTO -> { if (Objects.nonNull(transactionTopTenDTO.getId())) { if (transactionTopTenDTO.getSource().equals(CollectionSource.OFFICIAL)) { Collection collection = collectionRepo.findById(transactionTopTenDTO.getId()).orElse(null); if (Objects.nonNull(collection)) { transactionTopTenDTO.setPic(collection.getPic()); } } if (transactionTopTenDTO.getSource().equals(CollectionSource.TRANSFER)) { Asset asset = assetRepo.findById(transactionTopTenDTO.getId()).orElse(null); if (Objects.nonNull(asset)) { transactionTopTenDTO.setPic(asset.getPic()); } } } transactionTopTenDTO.setId(null); transactionTopTenDTO.setSource(null); }); return transactionTopTenDTOS; } public List queryFu() { Long userId = SecurityUtils.getAuthenticatedUser().getId(); String prefixName = sysConfigService.getString("fu_prefixName"); if (StringUtils.isBlank(prefixName)) { throw new BusinessException("缺少福分类配置"); } String[] split = prefixName.split(","); List prefixNames = Arrays.asList(split); return assetRepo.queryFu(userId, Constants.META_NORMAL_STATUS, prefixNames); } }