AssetService.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package com.izouma.nineth.service;
  2. import com.izouma.nineth.TokenHistory;
  3. import com.izouma.nineth.domain.*;
  4. import com.izouma.nineth.dto.PageQuery;
  5. import com.izouma.nineth.enums.AssetStatus;
  6. import com.izouma.nineth.enums.CollectionSource;
  7. import com.izouma.nineth.enums.CollectionType;
  8. import com.izouma.nineth.enums.OrderStatus;
  9. import com.izouma.nineth.event.TransferAssetEvent;
  10. import com.izouma.nineth.exception.BusinessException;
  11. import com.izouma.nineth.lock.RedisLockable;
  12. import com.izouma.nineth.repo.*;
  13. import com.izouma.nineth.utils.JpaUtils;
  14. import com.izouma.nineth.utils.SecurityUtils;
  15. import lombok.AllArgsConstructor;
  16. import lombok.extern.slf4j.Slf4j;
  17. import org.apache.commons.lang3.StringUtils;
  18. import org.springframework.beans.BeanUtils;
  19. import org.springframework.context.ApplicationContext;
  20. import org.springframework.data.domain.Page;
  21. import org.springframework.scheduling.annotation.Async;
  22. import org.springframework.scheduling.annotation.AsyncResult;
  23. import org.springframework.stereotype.Service;
  24. import java.math.BigDecimal;
  25. import java.time.LocalDateTime;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.concurrent.Future;
  29. @Service
  30. @AllArgsConstructor
  31. @Slf4j
  32. public class AssetService {
  33. private AssetRepo assetRepo;
  34. private UserRepo userRepo;
  35. private CollectionRepo collectionRepo;
  36. private ApplicationContext applicationContext;
  37. private OrderRepo orderRepo;
  38. private TokenHistoryRepo tokenHistoryRepo;
  39. private AssetMintService assetMintService;
  40. public Page<Asset> all(PageQuery pageQuery) {
  41. return assetRepo.findAll(JpaUtils.toSpecification(pageQuery, Asset.class), JpaUtils.toPageRequest(pageQuery));
  42. }
  43. @Async
  44. public Future<Asset> createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number) {
  45. Asset asset = Asset.create(collection, user);
  46. asset.setNumber(number);
  47. asset.setOrderId(orderId);
  48. asset.setPrice(price);
  49. asset.setIpfsUrl(assetMintService.ipfsUpload(collection.getPic().get(0).getUrl()));
  50. assetRepo.save(asset);
  51. TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
  52. .tokenId(asset.getTokenId())
  53. .fromUser(collection.getMinter())
  54. .fromUserId(collection.getMinterId())
  55. .fromAvatar(collection.getMinterAvatar())
  56. .toUser(user.getNickname())
  57. .toUserId(user.getId())
  58. .toAvatar(user.getAvatar())
  59. .operation(type)
  60. .price(price)
  61. .build());
  62. assetMintService.mint(asset, tokenHistory.getId());
  63. return new AsyncResult<>(asset);
  64. }
  65. @Async
  66. public Future<Asset> createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type, Integer number) {
  67. Asset asset = Asset.create(winItem, user);
  68. asset.setNumber(number);
  69. asset.setOrderId(orderId);
  70. asset.setPrice(price);
  71. asset.setIpfsUrl(assetMintService.ipfsUpload(winItem.getPic().get(0).getUrl()));
  72. assetRepo.save(asset);
  73. TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
  74. .tokenId(asset.getTokenId())
  75. .fromUser(winItem.getMinter())
  76. .fromUserId(winItem.getMinterId())
  77. .fromAvatar(winItem.getMinterAvatar())
  78. .toUser(user.getNickname())
  79. .toUserId(user.getId())
  80. .toAvatar(user.getAvatar())
  81. .operation(type)
  82. .price(price)
  83. .build());
  84. assetMintService.mint(asset, tokenHistory.getId());
  85. return new AsyncResult<>(asset);
  86. }
  87. public void publicShow(Long id) {
  88. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  89. if (asset.isPublicShow()) {
  90. return;
  91. }
  92. if (asset.getStatus() != AssetStatus.NORMAL) {
  93. throw new BusinessException("当前状态不可展示");
  94. }
  95. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  96. Collection collection = Collection.builder()
  97. .name(asset.getName())
  98. .pic(asset.getPic())
  99. .minter(asset.getMinter())
  100. .minterId(asset.getMinterId())
  101. .minterAvatar(asset.getMinterAvatar())
  102. .owner(owner.getNickname())
  103. .ownerId(owner.getId())
  104. .ownerAvatar(owner.getAvatar())
  105. .detail(asset.getDetail())
  106. .type(CollectionType.DEFAULT)
  107. .source(CollectionSource.TRANSFER)
  108. .sale(0)
  109. .stock(1)
  110. .total(1)
  111. .onShelf(true)
  112. .salable(false)
  113. .price(BigDecimal.valueOf(0))
  114. .properties(asset.getProperties())
  115. .canResale(asset.isCanResale())
  116. .royalties(asset.getRoyalties())
  117. .serviceCharge(asset.getServiceCharge())
  118. .assetId(id)
  119. .number(asset.getNumber())
  120. .build();
  121. collectionRepo.save(collection);
  122. asset.setPublicShow(true);
  123. asset.setPublicCollectionId(collection.getId());
  124. assetRepo.save(asset);
  125. }
  126. public void consignment(Long id, BigDecimal price) {
  127. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  128. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  129. if (StringUtils.isBlank(owner.getSettleAccountId())) {
  130. throw new BusinessException("请先绑定银行卡");
  131. }
  132. if (asset.isConsignment()) {
  133. throw new BusinessException("已寄售,请勿重新操作");
  134. }
  135. if (asset.getStatus() != AssetStatus.NORMAL) {
  136. throw new BusinessException("当前状态不可寄售");
  137. }
  138. if (asset.isPublicShow()) {
  139. cancelPublic(asset);
  140. }
  141. Collection collection = Collection.builder()
  142. .name(asset.getName())
  143. .pic(asset.getPic())
  144. .minter(asset.getMinter())
  145. .minterId(asset.getMinterId())
  146. .minterAvatar(asset.getMinterAvatar())
  147. .owner(owner.getNickname())
  148. .ownerId(owner.getId())
  149. .ownerAvatar(owner.getAvatar())
  150. .detail(asset.getDetail())
  151. .type(CollectionType.DEFAULT)
  152. .source(CollectionSource.TRANSFER)
  153. .sale(0)
  154. .stock(1)
  155. .total(1)
  156. .onShelf(true)
  157. .salable(true)
  158. .price(price)
  159. .properties(asset.getProperties())
  160. .canResale(asset.isCanResale())
  161. .royalties(asset.getRoyalties())
  162. .serviceCharge(asset.getServiceCharge())
  163. .assetId(id)
  164. .number(asset.getNumber())
  165. .build();
  166. collectionRepo.save(collection);
  167. asset.setPublicShow(true);
  168. asset.setConsignment(true);
  169. asset.setPublicCollectionId(collection.getId());
  170. asset.setSellPrice(price);
  171. assetRepo.save(asset);
  172. }
  173. public void cancelConsignment(Long id) {
  174. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  175. cancelConsignment(asset);
  176. }
  177. public void cancelConsignment(Asset asset) {
  178. if (asset.getPublicCollectionId() != null) {
  179. List<Order> orders = orderRepo.findByCollectionId(asset.getPublicCollectionId());
  180. if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) {
  181. throw new BusinessException("已有订单不可取消");
  182. }
  183. collectionRepo.findById(asset.getPublicCollectionId())
  184. .ifPresent(collection -> {
  185. collection.setSalable(false);
  186. collectionRepo.save(collection);
  187. });
  188. }
  189. asset.setConsignment(false);
  190. assetRepo.save(asset);
  191. }
  192. public void cancelPublic(Long id) {
  193. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  194. cancelPublic(asset);
  195. }
  196. public void cancelPublic(Asset asset) {
  197. if (!asset.isPublicShow()) {
  198. return;
  199. }
  200. if (asset.isConsignment()) {
  201. cancelConsignment(asset);
  202. }
  203. Collection collection = collectionRepo.findById(asset.getPublicCollectionId())
  204. .orElseThrow(new BusinessException("无展示记录"));
  205. collectionRepo.delete(collection);
  206. asset.setPublicShow(false);
  207. asset.setCollectionId(null);
  208. assetRepo.save(asset);
  209. }
  210. public void usePrivilege(Long assetId, Long privilegeId) {
  211. Asset asset = assetRepo.findById(assetId).orElseThrow(new BusinessException("无记录"));
  212. asset.getPrivileges().stream().filter(p -> p.getId().equals(privilegeId)).forEach(p -> {
  213. p.setOpened(true);
  214. p.setOpenTime(LocalDateTime.now());
  215. p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId());
  216. });
  217. assetRepo.save(asset);
  218. }
  219. @Async
  220. public void transfer(Asset asset, BigDecimal price, User toUser, String reason, Long orderId) {
  221. Asset newAsset = new Asset();
  222. BeanUtils.copyProperties(asset, newAsset);
  223. newAsset.setId(null);
  224. newAsset.setUserId(toUser.getId());
  225. newAsset.setOwner(toUser.getNickname());
  226. newAsset.setOwnerId(toUser.getId());
  227. newAsset.setOwnerAvatar(toUser.getAvatar());
  228. newAsset.setPublicShow(false);
  229. newAsset.setConsignment(false);
  230. newAsset.setPublicCollectionId(null);
  231. newAsset.setStatus(AssetStatus.NORMAL);
  232. newAsset.setPrice(price);
  233. newAsset.setSellPrice(null);
  234. newAsset.setOrderId(orderId);
  235. assetRepo.save(newAsset);
  236. asset.setPublicShow(false);
  237. asset.setConsignment(false);
  238. asset.setPublicCollectionId(null);
  239. asset.setStatus(AssetStatus.GIFTED);
  240. asset.setOwner(toUser.getNickname());
  241. asset.setOwnerId(toUser.getId());
  242. asset.setOwnerAvatar(toUser.getAvatar());
  243. assetRepo.save(asset);
  244. tokenHistoryRepo.save(TokenHistory.builder()
  245. .tokenId(asset.getTokenId())
  246. .fromUser(asset.getOwner())
  247. .fromUserId(asset.getOwnerId())
  248. .fromAvatar(asset.getOwnerAvatar())
  249. .toUser(toUser.getNickname())
  250. .toUserId(toUser.getId())
  251. .toAvatar(toUser.getAvatar())
  252. .operation(reason)
  253. .build());
  254. if (orderId != null) {
  255. applicationContext.publishEvent(new TransferAssetEvent(this, true, newAsset));
  256. }
  257. }
  258. public List<TokenHistory> tokenHistory(String tokenId, Long assetId) {
  259. if (tokenId == null) {
  260. if (assetId == null) return new ArrayList<>();
  261. tokenId = assetRepo.findById(assetId).map(Asset::getTokenId).orElse(null);
  262. }
  263. if (tokenId == null) return new ArrayList<>();
  264. return tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(tokenId);
  265. }
  266. @RedisLockable(key = "#id", expiration = 60, isWaiting = true)
  267. public void testLock(String id, String i) throws InterruptedException {
  268. Thread.sleep(1000);
  269. log.info("" + i);
  270. }
  271. public void setHistory() {
  272. List<Asset> assets = assetRepo.findByCreatedAtBefore(LocalDateTime.of(2021, 11, 22, 23, 59, 59));
  273. assets.parallelStream().forEach(asset -> {
  274. try {
  275. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException(""));
  276. Order order = orderRepo.findById(asset.getOrderId()).orElseThrow(new BusinessException(""));
  277. TokenHistory t = TokenHistory.builder()
  278. .tokenId(asset.getTokenId())
  279. .fromUser(asset.getMinter())
  280. .fromUserId(asset.getMinterId())
  281. .fromAvatar(asset.getMinterAvatar())
  282. .toUser(owner.getNickname())
  283. .toUserId(owner.getId())
  284. .toAvatar(owner.getAvatar())
  285. .operation("出售")
  286. .price(order.getPrice())
  287. .build();
  288. t.setCreatedAt(asset.getCreatedAt());
  289. tokenHistoryRepo.save(t);
  290. } catch (Exception e) {
  291. }
  292. });
  293. }
  294. }