| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- package com.izouma.nineth.service;
- import com.izouma.nineth.TokenHistory;
- import com.izouma.nineth.domain.Collection;
- import com.izouma.nineth.domain.*;
- import com.izouma.nineth.dto.PageQuery;
- import com.izouma.nineth.dto.UserHistory;
- import com.izouma.nineth.enums.AssetStatus;
- import com.izouma.nineth.enums.CollectionSource;
- import com.izouma.nineth.enums.CollectionType;
- import com.izouma.nineth.enums.OrderStatus;
- import com.izouma.nineth.event.TransferAssetEvent;
- import com.izouma.nineth.exception.BusinessException;
- import com.izouma.nineth.lock.RedisLockable;
- 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.lang3.StringUtils;
- import org.springframework.beans.BeanUtils;
- import org.springframework.context.ApplicationContext;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import java.math.BigDecimal;
- import java.time.LocalDateTime;
- import java.time.temporal.ChronoUnit;
- import java.util.*;
- import java.util.stream.Collectors;
- @Service
- @AllArgsConstructor
- @Slf4j
- public class AssetService {
- private AssetRepo assetRepo;
- private UserRepo userRepo;
- private CollectionRepo collectionRepo;
- private ApplicationContext applicationContext;
- private OrderRepo orderRepo;
- private TokenHistoryRepo tokenHistoryRepo;
- private AssetMintService assetMintService;
- private SysConfigService sysConfigService;
- public Page<Asset> all(PageQuery pageQuery) {
- return assetRepo.findAll(JpaUtils.toSpecification(pageQuery, Asset.class), JpaUtils.toPageRequest(pageQuery));
- }
- public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number) {
- Asset asset = Asset.create(collection, user);
- asset.setTokenId(TokenUtils.genTokenId());
- asset.setNumber(number);
- asset.setOrderId(orderId);
- asset.setPrice(price);
- assetRepo.save(asset);
- tokenHistoryRepo.save(TokenHistory.builder()
- .tokenId(asset.getTokenId())
- .fromUser(collection.getMinter())
- .fromUserId(collection.getMinterId())
- .fromAvatar(collection.getMinterAvatar())
- .toUser(user.getNickname())
- .toUserId(user.getId())
- .toAvatar(user.getAvatar())
- .operation(type)
- .price(price)
- .projectId(asset.getProjectId())
- .build());
- assetMintService.mint(asset);
- return asset;
- }
- public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type, Integer number) {
- Asset asset = Asset.create(winItem, user);
- asset.setTokenId(TokenUtils.genTokenId());
- asset.setNumber(number);
- asset.setOrderId(orderId);
- asset.setPrice(price);
- assetRepo.saveAndFlush(asset);
- tokenHistoryRepo.save(TokenHistory.builder()
- .tokenId(asset.getTokenId())
- .fromUser(winItem.getMinter())
- .fromUserId(winItem.getMinterId())
- .fromAvatar(winItem.getMinterAvatar())
- .toUser(user.getNickname())
- .toUserId(user.getId())
- .toAvatar(user.getAvatar())
- .operation(type)
- .price(price)
- .projectId(asset.getProjectId())
- .build());
- assetMintService.mint(asset.getId(), user.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.isPublicShow()) {
- return;
- }
- if (asset.getStatus() != AssetStatus.NORMAL) {
- throw new BusinessException("当前状态不可展示");
- }
- User owner = 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())
- .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())
- .projectId(asset.getProjectId())
- .build();
- collectionRepo.save(collection);
- asset.setPublicShow(true);
- asset.setPublicCollectionId(collection.getId());
- assetRepo.save(asset);
- }
- public void consignment(Long id, BigDecimal price) {
- Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
- if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
- throw new BusinessException("此藏品不属于你");
- }
- int holdDays = sysConfigService.getInt("hold_days");
- if (ChronoUnit.DAYS.between(asset.getCreatedAt(), LocalDateTime.now()) < holdDays) {
- throw new BusinessException("需持有满" + holdDays + "天才能寄售上架");
- }
- User owner = userRepo.findById(asset.getUserId()).orElseThrow(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);
- }
- 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())
- .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())
- .projectId(asset.getProjectId())
- .build();
- collectionRepo.save(collection);
- asset.setPublicShow(true);
- asset.setConsignment(true);
- asset.setPublicCollectionId(collection.getId());
- asset.setSellPrice(price);
- assetRepo.save(asset);
- }
- 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<Order> 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.save(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);
- asset.setPublicShow(false);
- asset.setPublicCollectionId(null);
- assetRepo.save(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 -> {
- p.setOpened(true);
- p.setOpenTime(LocalDateTime.now());
- p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId());
- });
- assetRepo.save(asset);
- }
- @Async
- public void transfer(Asset asset, BigDecimal price, User toUser, String reason, Long orderId) {
- Asset newAsset = new Asset();
- BeanUtils.copyProperties(asset, newAsset);
- newAsset.setId(null);
- newAsset.setUserId(toUser.getId());
- newAsset.setOwner(toUser.getNickname());
- newAsset.setOwnerId(toUser.getId());
- newAsset.setOwnerAvatar(toUser.getAvatar());
- newAsset.setPublicShow(false);
- newAsset.setConsignment(false);
- newAsset.setPublicCollectionId(null);
- newAsset.setStatus(AssetStatus.NORMAL);
- newAsset.setPrice(price);
- newAsset.setSellPrice(null);
- newAsset.setOrderId(orderId);
- newAsset.setFromAssetId(asset.getId());
- assetRepo.save(newAsset);
- tokenHistoryRepo.save(TokenHistory.builder()
- .tokenId(asset.getTokenId())
- .fromUser(asset.getOwner())
- .fromUserId(asset.getOwnerId())
- .fromAvatar(asset.getOwnerAvatar())
- .toUser(toUser.getNickname())
- .toUserId(toUser.getId())
- .toAvatar(toUser.getAvatar())
- .operation(reason)
- .price("转赠".equals(reason) ? null : price)
- .projectId(asset.getProjectId())
- .build());
- asset.setPublicShow(false);
- asset.setConsignment(false);
- asset.setPublicCollectionId(null);
- asset.setStatus("转赠".equals(reason) ? AssetStatus.GIFTED : AssetStatus.TRANSFERRED);
- asset.setOwner(toUser.getNickname());
- asset.setOwnerId(toUser.getId());
- asset.setOwnerAvatar(toUser.getAvatar());
- asset.setOutTime(LocalDateTime.now());
- assetRepo.save(asset);
- if (orderId != null) {
- applicationContext.publishEvent(new TransferAssetEvent(this, true, newAsset));
- }
- }
- public List<TokenHistory> 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);
- }
- @RedisLockable(key = "#id", expiration = 60, isWaiting = true)
- public void testLock(String id, String i) throws InterruptedException {
- Thread.sleep(1000);
- log.info("" + i);
- }
- public void setHistory() {
- List<Asset> assets = assetRepo.findByCreatedAtBefore(LocalDateTime.of(2021, 11, 22, 23, 59, 59));
- assets.parallelStream().forEach(asset -> {
- try {
- User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException(""));
- Order order = orderRepo.findById(asset.getOrderId()).orElseThrow(new BusinessException(""));
- TokenHistory t = TokenHistory.builder()
- .tokenId(asset.getTokenId())
- .fromUser(asset.getMinter())
- .fromUserId(asset.getMinterId())
- .fromAvatar(asset.getMinterAvatar())
- .toUser(owner.getNickname())
- .toUserId(owner.getId())
- .toAvatar(owner.getAvatar())
- .operation("出售")
- .price(order.getPrice())
- .projectId(asset.getProjectId())
- .build();
- t.setCreatedAt(asset.getCreatedAt());
- tokenHistoryRepo.save(t);
- } catch (Exception e) {
- }
- });
- }
- public Page<UserHistory> userHistory(Long userId, int projectId, Pageable pageable) {
- Page<TokenHistory> page = tokenHistoryRepo.userHistoryAndProjectId(userId, projectId, pageable);
- Set<String> tokenIds = page.stream().map(TokenHistory::getTokenId).collect(Collectors.toSet());
- List<Asset> assets = tokenIds.isEmpty() ? new ArrayList<>() : assetRepo.findByTokenIdIn(tokenIds);
- return page.map(tokenHistory -> {
- UserHistory userHistory = new UserHistory();
- BeanUtils.copyProperties(tokenHistory, userHistory);
- Optional<Asset> 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("空投");
- break;
- case "转赠":
- userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送");
- break;
- }
- return userHistory;
- });
- }
- public Map<User, Integer> holdQuery(List<String> names, LocalDateTime startTime, LocalDateTime endTime) {
- Map<User, Integer> result = new HashMap<>();
- userRepo.findAll().stream().parallel().forEach(user -> {
- List<Asset> assets = assetRepo.findByUserId(user.getId());
- assets = assets.stream().filter(a -> names.stream().anyMatch(n -> n.equals(a.getName())))
- .collect(Collectors.toList());
- if (assets.size() < names.size()) {
- return;
- }
- assets = assets.stream().filter(a -> a.getCreatedAt().isBefore(startTime))
- .collect(Collectors.toList());
- if (assets.size() < names.size()) {
- return;
- }
- assets = assets.stream().filter(a -> {
- if (a.getStatus() != AssetStatus.GIFTED && a.getStatus() != AssetStatus.TRANSFERRED) {
- return true;
- } else {
- Asset a1 = assetRepo.findFirstByTokenIdAndCreatedAtAfterOrderByCreatedAt(a.getTokenId(), a.getCreatedAt());
- return a1 != null && a.getCreatedAt().isAfter(endTime);
- }
- })
- .collect(Collectors.toList());
- boolean flag = true;
- Map<String, Integer> map = new HashMap<>();
- for (String name : names) {
- int c = (int) assets.stream().filter(a -> name.equals(a.getName())).count();
- map.put(name, c);
- flag = flag && (c > 0);
- }
- if (flag) {
- result.put(user, map.values().stream().mapToInt(i -> i).min().orElse(0));
- }
- });
- return result;
- }
- }
|