AssetService.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. package com.izouma.nineth.service;
  2. import cn.hutool.core.convert.Convert;
  3. import com.izouma.nineth.TokenHistory;
  4. import com.izouma.nineth.config.GeneralProperties;
  5. import com.izouma.nineth.domain.Collection;
  6. import com.izouma.nineth.domain.*;
  7. import com.izouma.nineth.dto.PageQuery;
  8. import com.izouma.nineth.dto.UserHistory;
  9. import com.izouma.nineth.enums.AssetStatus;
  10. import com.izouma.nineth.enums.CollectionSource;
  11. import com.izouma.nineth.enums.CollectionType;
  12. import com.izouma.nineth.enums.OrderStatus;
  13. import com.izouma.nineth.event.TransferAssetEvent;
  14. import com.izouma.nineth.exception.BusinessException;
  15. import com.izouma.nineth.repo.*;
  16. import com.izouma.nineth.utils.JpaUtils;
  17. import com.izouma.nineth.utils.SecurityUtils;
  18. import com.izouma.nineth.utils.TokenUtils;
  19. import lombok.AllArgsConstructor;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.apache.commons.lang3.ObjectUtils;
  22. import org.apache.commons.lang3.StringUtils;
  23. import org.apache.rocketmq.spring.core.RocketMQTemplate;
  24. import org.springframework.beans.BeanUtils;
  25. import org.springframework.cache.annotation.Cacheable;
  26. import org.springframework.context.ApplicationContext;
  27. import org.springframework.data.domain.Page;
  28. import org.springframework.data.domain.Pageable;
  29. import org.springframework.scheduling.annotation.Async;
  30. import org.springframework.scheduling.annotation.Scheduled;
  31. import org.springframework.security.crypto.password.PasswordEncoder;
  32. import org.springframework.stereotype.Service;
  33. import javax.persistence.criteria.Predicate;
  34. import java.math.BigDecimal;
  35. import java.time.LocalDateTime;
  36. import java.time.temporal.ChronoUnit;
  37. import java.util.*;
  38. import java.util.concurrent.ExecutionException;
  39. import java.util.concurrent.ForkJoinPool;
  40. import java.util.stream.Collectors;
  41. @Service
  42. @AllArgsConstructor
  43. @Slf4j
  44. public class AssetService {
  45. private AssetRepo assetRepo;
  46. private UserRepo userRepo;
  47. private CollectionRepo collectionRepo;
  48. private ApplicationContext applicationContext;
  49. private OrderRepo orderRepo;
  50. private TokenHistoryRepo tokenHistoryRepo;
  51. private SysConfigService sysConfigService;
  52. private RocketMQTemplate rocketMQTemplate;
  53. private GeneralProperties generalProperties;
  54. private ShowroomRepo showroomRepo;
  55. private ShowCollectionRepo showCollectionRepo;
  56. private CollectionPrivilegeRepo collectionPrivilegeRepo;
  57. private PasswordEncoder passwordEncoder;
  58. public Page<Asset> all(PageQuery pageQuery) {
  59. Page<Asset> all = assetRepo
  60. .findAll(JpaUtils.toSpecification(pageQuery, Asset.class), JpaUtils.toPageRequest(pageQuery));
  61. Map<String, Object> query = pageQuery.getQuery();
  62. if (query.containsKey("userId")) {
  63. List<Long> orderId = orderRepo
  64. .findAllByUserIdAndOpenedFalse(Convert.convert(Long.class, query.get("userId")));
  65. return all.map(asset -> {
  66. if (orderId.contains(asset.getOrderId())) {
  67. asset.setOpened(false);
  68. }
  69. return asset;
  70. });
  71. }
  72. return all;
  73. }
  74. public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number) {
  75. Asset asset = Asset.create(collection, user);
  76. asset.setTokenId(TokenUtils.genTokenId());
  77. asset.setNumber(number);
  78. asset.setOasisId(collection.getOasisId());
  79. asset.setOrderId(orderId);
  80. asset.setPrice(price);
  81. assetRepo.saveAndFlush(asset);
  82. tokenHistoryRepo.save(TokenHistory.builder()
  83. .tokenId(asset.getTokenId())
  84. .fromUser(collection.getMinter())
  85. .fromUserId(collection.getMinterId())
  86. .fromAvatar(collection.getMinterAvatar())
  87. .toUser(user.getNickname())
  88. .toUserId(user.getId())
  89. .toAvatar(user.getAvatar())
  90. .operation(type)
  91. .price(price)
  92. .build());
  93. rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId());
  94. return asset;
  95. }
  96. public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type,
  97. Integer number, Integer holdDays) {
  98. Asset asset = Asset.create(winItem, user, holdDays);
  99. asset.setTokenId(TokenUtils.genTokenId());
  100. asset.setNumber(number);
  101. asset.setOasisId(winItem.getOasisId());
  102. asset.setOrderId(orderId);
  103. asset.setPrice(price);
  104. assetRepo.saveAndFlush(asset);
  105. tokenHistoryRepo.save(TokenHistory.builder()
  106. .tokenId(asset.getTokenId())
  107. .fromUser(winItem.getMinter())
  108. .fromUserId(winItem.getMinterId())
  109. .fromAvatar(winItem.getMinterAvatar())
  110. .toUser(user.getNickname())
  111. .toUserId(user.getId())
  112. .toAvatar(user.getAvatar())
  113. .operation(type)
  114. .price(price)
  115. .build());
  116. rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId());
  117. return asset;
  118. }
  119. public void publicShow(Long id) {
  120. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  121. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  122. throw new BusinessException("此藏品不属于你");
  123. }
  124. if (asset.isPublicShow()) {
  125. return;
  126. }
  127. if (asset.getStatus() != AssetStatus.NORMAL) {
  128. throw new BusinessException("当前状态不可展示");
  129. }
  130. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  131. Collection collection = Collection.builder()
  132. .name(asset.getName())
  133. .pic(asset.getPic())
  134. .minter(asset.getMinter())
  135. .minterId(asset.getMinterId())
  136. .minterAvatar(asset.getMinterAvatar())
  137. .owner(owner.getNickname())
  138. .oasisId(asset.getOasisId())
  139. .ownerId(owner.getId())
  140. .ownerAvatar(owner.getAvatar())
  141. .detail(asset.getDetail())
  142. .type(CollectionType.DEFAULT)
  143. .source(CollectionSource.TRANSFER)
  144. .sale(0)
  145. .stock(1)
  146. .total(1)
  147. .onShelf(true)
  148. .salable(false)
  149. .price(BigDecimal.valueOf(0))
  150. .properties(asset.getProperties())
  151. .canResale(asset.isCanResale())
  152. .royalties(asset.getRoyalties())
  153. .serviceCharge(asset.getServiceCharge())
  154. .assetId(id)
  155. .number(asset.getNumber())
  156. .build();
  157. collectionRepo.save(collection);
  158. asset.setPublicShow(true);
  159. asset.setPublicCollectionId(collection.getId());
  160. assetRepo.save(asset);
  161. }
  162. public synchronized void consignment(Long id, BigDecimal price, String tradeCode) {
  163. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  164. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  165. throw new BusinessException("此藏品不属于你");
  166. }
  167. int holdDays;
  168. if (ObjectUtils.isEmpty(asset.getHoldDays())) {
  169. holdDays = sysConfigService.getInt("hold_days");
  170. } else {
  171. holdDays = asset.getHoldDays();
  172. }
  173. if (ChronoUnit.DAYS.between(asset.getCreatedAt(), LocalDateTime.now()) < holdDays) {
  174. throw new BusinessException("需持有满" + holdDays + "天才能寄售上架");
  175. }
  176. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
  177. if (!passwordEncoder.matches(tradeCode, owner.getTradeCode())) {
  178. throw new BusinessException("交易密码错误");
  179. }
  180. if (StringUtils.isBlank(owner.getSettleAccountId())) {
  181. throw new BusinessException("请先绑定银行卡");
  182. }
  183. if (asset.isConsignment()) {
  184. throw new BusinessException("已寄售,请勿重新操作");
  185. }
  186. if (asset.getStatus() != AssetStatus.NORMAL) {
  187. throw new BusinessException("当前状态不可寄售");
  188. }
  189. if (asset.isPublicShow()) {
  190. cancelPublic(asset);
  191. }
  192. //寄售中的展厅需要先删除展厅
  193. if (CollectionType.SHOWROOM.equals(asset.getType())) {
  194. if (showroomRepo.findByAssetId(id).isPresent()) {
  195. throw new BusinessException("请先删除展厅");
  196. }
  197. }
  198. Collection collection = Collection.builder()
  199. .name(asset.getName())
  200. .pic(asset.getPic())
  201. .minter(asset.getMinter())
  202. .minterId(asset.getMinterId())
  203. .minterAvatar(asset.getMinterAvatar())
  204. .owner(owner.getNickname())
  205. .ownerId(owner.getId())
  206. .oasisId(asset.getOasisId())
  207. .ownerAvatar(owner.getAvatar())
  208. .detail(asset.getDetail())
  209. .type(CollectionType.DEFAULT)
  210. .source(CollectionSource.TRANSFER)
  211. .sale(0)
  212. .stock(1)
  213. .total(1)
  214. .onShelf(true)
  215. .salable(true)
  216. .price(price)
  217. .properties(asset.getProperties())
  218. .canResale(asset.isCanResale())
  219. .royalties(asset.getRoyalties())
  220. .serviceCharge(asset.getServiceCharge())
  221. .assetId(id)
  222. .number(asset.getNumber())
  223. .build();
  224. collectionRepo.save(collection);
  225. asset.setPublicShow(true);
  226. asset.setConsignment(true);
  227. asset.setPublicCollectionId(collection.getId());
  228. asset.setSellPrice(price);
  229. assetRepo.save(asset);
  230. }
  231. public void cancelConsignment(Long id) {
  232. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  233. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  234. throw new BusinessException("此藏品不属于你");
  235. }
  236. cancelConsignment(asset);
  237. }
  238. public void cancelConsignment(Asset asset) {
  239. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  240. throw new BusinessException("此藏品不属于你");
  241. }
  242. if (asset.getPublicCollectionId() != null) {
  243. List<Order> orders = orderRepo.findByCollectionId(asset.getPublicCollectionId());
  244. if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) {
  245. throw new BusinessException("已有订单不可取消");
  246. }
  247. collectionRepo.findById(asset.getPublicCollectionId())
  248. .ifPresent(collection -> {
  249. collection.setSalable(false);
  250. collectionRepo.save(collection);
  251. });
  252. }
  253. asset.setConsignment(false);
  254. assetRepo.save(asset);
  255. }
  256. public void cancelPublic(Long id) {
  257. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  258. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  259. throw new BusinessException("此藏品不属于你");
  260. }
  261. cancelPublic(asset);
  262. }
  263. public void cancelPublic(Asset asset) {
  264. if (!asset.getUserId().equals(SecurityUtils.getAuthenticatedUser().getId())) {
  265. throw new BusinessException("此藏品不属于你");
  266. }
  267. if (!asset.isPublicShow()) {
  268. return;
  269. }
  270. if (asset.isConsignment()) {
  271. cancelConsignment(asset);
  272. }
  273. Collection collection = collectionRepo.findById(asset.getPublicCollectionId())
  274. .orElseThrow(new BusinessException("无展示记录"));
  275. collectionRepo.delete(collection);
  276. // 如果展厅有此藏品
  277. showCollectionRepo.deleteAllByCollectionId(asset.getPublicCollectionId());
  278. asset.setPublicShow(false);
  279. asset.setPublicCollectionId(null);
  280. assetRepo.save(asset);
  281. }
  282. public void usePrivilege(Long assetId, Long privilegeId) {
  283. Asset asset = assetRepo.findById(assetId).orElseThrow(new BusinessException("无记录"));
  284. asset.getPrivileges().stream().filter(p -> p.getId().equals(privilegeId)).forEach(p -> {
  285. if (!p.getName().equals("铸造")) {
  286. p.setOpened(true);
  287. p.setOpenTime(LocalDateTime.now());
  288. p.setOpenedBy(SecurityUtils.getAuthenticatedUser().getId());
  289. }
  290. });
  291. assetRepo.save(asset);
  292. }
  293. @Async
  294. public void transfer(Asset asset, BigDecimal price, User toUser, String reason, Long orderId) {
  295. Asset newAsset = new Asset();
  296. BeanUtils.copyProperties(asset, newAsset);
  297. newAsset.setId(null);
  298. newAsset.setUserId(toUser.getId());
  299. newAsset.setOwner(toUser.getNickname());
  300. newAsset.setOwnerId(toUser.getId());
  301. newAsset.setOwnerAvatar(toUser.getAvatar());
  302. newAsset.setPublicShow(false);
  303. newAsset.setConsignment(false);
  304. newAsset.setPublicCollectionId(null);
  305. newAsset.setStatus(AssetStatus.NORMAL);
  306. newAsset.setPrice(price);
  307. newAsset.setSellPrice(null);
  308. newAsset.setOrderId(orderId);
  309. newAsset.setOasisId(asset.getOasisId());
  310. newAsset.setFromAssetId(asset.getId());
  311. newAsset.setType(CollectionType.DEFAULT);
  312. assetRepo.save(newAsset);
  313. tokenHistoryRepo.save(TokenHistory.builder()
  314. .tokenId(asset.getTokenId())
  315. .fromUser(asset.getOwner())
  316. .fromUserId(asset.getOwnerId())
  317. .fromAvatar(asset.getOwnerAvatar())
  318. .toUser(toUser.getNickname())
  319. .toUserId(toUser.getId())
  320. .toAvatar(toUser.getAvatar())
  321. .operation(reason)
  322. .price("转赠".equals(reason) ? null : price)
  323. .build());
  324. asset.setPublicShow(false);
  325. asset.setConsignment(false);
  326. asset.setPublicCollectionId(null);
  327. asset.setStatus("转赠".equals(reason) ? AssetStatus.GIFTED : AssetStatus.TRANSFERRED);
  328. asset.setOwner(toUser.getNickname());
  329. asset.setOwnerId(toUser.getId());
  330. asset.setOwnerAvatar(toUser.getAvatar());
  331. assetRepo.save(asset);
  332. if (orderId != null) {
  333. applicationContext.publishEvent(new TransferAssetEvent(this, true, newAsset));
  334. }
  335. //vip权限转让
  336. CollectionPrivilege collectionPrivilege = collectionPrivilegeRepo.findByCollectionId(asset.getCollectionId());
  337. if (ObjectUtils.isNotEmpty(collectionPrivilege)) {
  338. if (collectionPrivilege.isVip()) {
  339. //更新vip信息
  340. userRepo.updateVipPurchase(toUser.getId(), 1);
  341. userRepo.updateVipPurchase(asset.getUserId(), 0);
  342. }
  343. }
  344. }
  345. public List<TokenHistory> tokenHistory(String tokenId, Long assetId) {
  346. if (tokenId == null) {
  347. if (assetId == null) return new ArrayList<>();
  348. tokenId = assetRepo.findById(assetId).map(Asset::getTokenId).orElse(null);
  349. }
  350. if (tokenId == null) return new ArrayList<>();
  351. return tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(tokenId);
  352. }
  353. public void setHistory() {
  354. List<Asset> assets = assetRepo.findByCreatedAtBefore(LocalDateTime.of(2021, 11, 22, 23, 59, 59));
  355. assets.parallelStream().forEach(asset -> {
  356. try {
  357. User owner = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException(""));
  358. Order order = orderRepo.findById(asset.getOrderId()).orElseThrow(new BusinessException(""));
  359. TokenHistory t = TokenHistory.builder()
  360. .tokenId(asset.getTokenId())
  361. .fromUser(asset.getMinter())
  362. .fromUserId(asset.getMinterId())
  363. .fromAvatar(asset.getMinterAvatar())
  364. .toUser(owner.getNickname())
  365. .toUserId(owner.getId())
  366. .toAvatar(owner.getAvatar())
  367. .operation("出售")
  368. .price(order.getPrice())
  369. .build();
  370. t.setCreatedAt(asset.getCreatedAt());
  371. tokenHistoryRepo.save(t);
  372. } catch (Exception e) {
  373. }
  374. });
  375. }
  376. public Page<UserHistory> userHistory(Long userId, Long toUserId, Long fromUserId, Pageable pageable) {
  377. Page<TokenHistory> page;
  378. if (ObjectUtils.isNotEmpty(toUserId)) {
  379. page = tokenHistoryRepo.userHistoryTo(userId, toUserId, pageable);
  380. } else if (ObjectUtils.isNotEmpty(fromUserId)) {
  381. page = tokenHistoryRepo.userHistoryFrom(userId, fromUserId, pageable);
  382. } else {
  383. page = tokenHistoryRepo.userHistory(userId, pageable);
  384. }
  385. Set<String> tokenIds = page.stream().map(TokenHistory::getTokenId).collect(Collectors.toSet());
  386. List<Asset> assets = tokenIds.isEmpty() ? new ArrayList<>() : assetRepo.findByTokenIdIn(tokenIds);
  387. return page.map(tokenHistory -> {
  388. UserHistory userHistory = new UserHistory();
  389. BeanUtils.copyProperties(tokenHistory, userHistory);
  390. Optional<Asset> asset = assets.stream().filter(a -> a.getTokenId().equals(tokenHistory.getTokenId()))
  391. .findAny();
  392. userHistory.setAssetName(asset.map(Asset::getName).orElse(null));
  393. userHistory.setPic(asset.map(Asset::getPic).orElse(new ArrayList<>()));
  394. switch (tokenHistory.getOperation()) {
  395. case "出售":
  396. case "转让":
  397. userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出");
  398. break;
  399. case "空投":
  400. userHistory.setDescription("空投");
  401. break;
  402. case "转赠":
  403. userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送");
  404. break;
  405. }
  406. return userHistory;
  407. });
  408. }
  409. public Page<UserHistory> userHistory(Long userId, PageQuery pageQuery) {
  410. Page<TokenHistory> page = tokenHistoryRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
  411. List<Predicate> and = JpaUtils
  412. .toPredicates(pageQuery, TokenHistory.class, root, criteriaQuery, criteriaBuilder);
  413. Map<String, Object> query = pageQuery.getQuery();
  414. if (ObjectUtils.isEmpty(query.get("toUserId")) && ObjectUtils.isEmpty(query.get("fromUserId"))) {
  415. and.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("toUserId"), userId), criteriaBuilder
  416. .equal(root.get("fromUserId"), userId)));
  417. } else {
  418. if (ObjectUtils.isNotEmpty(query.get("toUserId"))) {
  419. and.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("toUserId"), userId)));
  420. } else {
  421. and.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("fromUserId"), userId)));
  422. }
  423. }
  424. return criteriaBuilder.and(and.toArray(new Predicate[0]));
  425. }), JpaUtils.toPageRequest(pageQuery));
  426. Set<String> tokenIds = page.stream().map(TokenHistory::getTokenId).collect(Collectors.toSet());
  427. List<Asset> assets = tokenIds.isEmpty() ? new ArrayList<>() : assetRepo.findByTokenIdIn(tokenIds);
  428. return page.map(tokenHistory -> {
  429. UserHistory userHistory = new UserHistory();
  430. BeanUtils.copyProperties(tokenHistory, userHistory);
  431. Optional<Asset> asset = assets.stream().filter(a -> a.getTokenId().equals(tokenHistory.getTokenId()))
  432. .findAny();
  433. userHistory.setAssetName(asset.map(Asset::getName).orElse(null));
  434. userHistory.setPic(asset.map(Asset::getPic).orElse(new ArrayList<>()));
  435. switch (tokenHistory.getOperation()) {
  436. case "出售":
  437. case "转让":
  438. userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "作品交易——买入" : "作品交易——售出");
  439. break;
  440. case "空投":
  441. userHistory.setDescription("空投");
  442. break;
  443. case "转赠":
  444. userHistory.setDescription(tokenHistory.getToUserId().equals(userId) ? "他人赠送" : "作品赠送");
  445. break;
  446. }
  447. return userHistory;
  448. });
  449. }
  450. public String mint(LocalDateTime time) {
  451. if (time == null) {
  452. time = LocalDateTime.now();
  453. }
  454. for (Asset asset : assetRepo.toMint(time)) {
  455. rocketMQTemplate.syncSend(generalProperties.getMintTopic(), asset.getId());
  456. }
  457. return "ok";
  458. }
  459. @Cacheable(value = "userStat", key = "#userId")
  460. public Map<String, BigDecimal> breakdown(Long userId) {
  461. List<TokenHistory> page = tokenHistoryRepo.userHistory(userId);
  462. BigDecimal sale = page.stream()
  463. .filter(th -> th.getFromUserId().equals(userId) && ObjectUtils.isNotEmpty(th.getPrice()))
  464. .map(TokenHistory::getPrice)
  465. .reduce(BigDecimal.ZERO, BigDecimal::add);
  466. BigDecimal buy = page.stream()
  467. .filter(th -> th.getToUserId().equals(userId) && ObjectUtils.isNotEmpty(th.getPrice()))
  468. .map(TokenHistory::getPrice)
  469. .reduce(BigDecimal.ZERO, BigDecimal::add);
  470. Map<String, BigDecimal> map = new HashMap<>();
  471. map.put("sale", sale);
  472. map.put("buy", buy);
  473. return map;
  474. }
  475. public void transferCDN() throws ExecutionException, InterruptedException {
  476. ForkJoinPool customThreadPool = new ForkJoinPool(100);
  477. customThreadPool.submit(() -> {
  478. collectionRepo.selectResource().parallelStream().forEach(list -> {
  479. for (int i = 0; i < list.size(); i++) {
  480. list.set(i, replaceCDN(list.get(i)));
  481. }
  482. collectionRepo.updateCDN(Long.parseLong(list.get(0)),
  483. list.get(1),
  484. list.get(2),
  485. list.get(3),
  486. list.get(4),
  487. list.get(5));
  488. });
  489. assetRepo.selectResource().parallelStream().forEach(list -> {
  490. for (int i = 0; i < list.size(); i++) {
  491. list.set(i, replaceCDN(list.get(i)));
  492. }
  493. assetRepo.updateCDN(Long.parseLong(list.get(0)),
  494. list.get(1),
  495. list.get(2),
  496. list.get(3),
  497. list.get(4),
  498. list.get(5));
  499. });
  500. }).get();
  501. }
  502. public String replaceCDN(String url) {
  503. if (url == null) return null;
  504. return url.replaceAll("https://raex-meta\\.oss-cn-shenzhen\\.aliyuncs\\.com",
  505. "https://cdn.raex.vip");
  506. }
  507. @Scheduled(cron = "0 0 0/1 * * ?")
  508. public void offTheShelf() {
  509. LocalDateTime lastTime = LocalDateTime.now().minusHours(120);
  510. Set<Long> assetIds = collectionRepo
  511. .findResaleCollectionPriceOver20K(BigDecimal
  512. .valueOf(20000L), CollectionSource.TRANSFER, lastTime, true);
  513. assetIds.forEach(this::cancelConsignmentBySystem);
  514. }
  515. public void cancelConsignmentBySystem(Long id) {
  516. Asset asset = assetRepo.findById(id).orElseThrow(new BusinessException("无记录"));
  517. if (asset.getPublicCollectionId() != null) {
  518. List<Order> orders = orderRepo.findByCollectionId(asset.getPublicCollectionId());
  519. if (orders.stream().anyMatch(o -> o.getStatus() != OrderStatus.CANCELLED)) {
  520. throw new BusinessException("已有订单不可取消");
  521. }
  522. collectionRepo.findById(asset.getPublicCollectionId())
  523. .ifPresent(collection -> {
  524. collection.setSalable(false);
  525. collectionRepo.save(collection);
  526. });
  527. }
  528. asset.setConsignment(false);
  529. assetRepo.save(asset);
  530. }
  531. }