AssetService.java 24 KB

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