package com.izouma.nineth.service.nftdomain; import com.alibaba.fastjson.JSONArray; import com.izouma.nineth.domain.Asset; import com.izouma.nineth.domain.DomainOrder; import com.izouma.nineth.domain.User; import com.izouma.nineth.domain.nftdomain.DomainAsk; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.dto.nftdomain.DomainAskGroup; import com.izouma.nineth.dto.nftdomain.DomainResult; import com.izouma.nineth.enums.*; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.AssetRepo; import com.izouma.nineth.repo.DomainOrderRepo; import com.izouma.nineth.repo.UserRepo; import com.izouma.nineth.repo.nftdomain.DomainAskRepo; import com.izouma.nineth.service.AssetService; import com.izouma.nineth.service.UserBalanceService; import com.izouma.nineth.utils.JpaUtils; import com.izouma.nineth.utils.SecurityUtils; import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @Service @AllArgsConstructor public class DomainAskService { private final DomainAskRepo domainAskRepo; private final DomainOrderRepo domainOrderRepo; private final AssetRepo assetRepo; private final UserRepo userRepo; private final AssetService assetService; private final UserBalanceService userBalanceService; public Page all(PageQuery pageQuery) { return domainAskRepo .findAll(JpaUtils.toSpecification(pageQuery, DomainAsk.class), JpaUtils.toPageRequest(pageQuery)); } public BigDecimal getMaxPrice(Long domainOrderId) { return domainAskRepo.findMaxPrice(domainOrderId); } public DomainAsk create(Long domainOrderId, Long userId, BigDecimal price) { User user = userRepo.findById(userId).orElseThrow(new BusinessException("未找到用户")); DomainOrder domainOrder = domainOrderRepo.findById(domainOrderId).orElseThrow(new BusinessException("暂无该藏品")); Asset asset = assetRepo.findFirstByNameAndStatus("RID元宇宙域名 " + domainOrder.getDomainName(), AssetStatus.NORMAL); if (asset == null) { throw new BusinessException("未找到对应藏品。"); } if (asset.isConsignment()) { throw new BusinessException("藏品已经寄售,无法出价"); } if (userId.equals(asset.getUserId())) { throw new BusinessException("无法叫价自己的藏品"); } Set domainAskStatuses = new HashSet<>(); domainAskStatuses.add(DomainAskStatus.ASKING); if (domainAskRepo .countByAssetIdAndUserIdAndStatusInAndDelFalse(asset.getId(), userId, domainAskStatuses) > 0) { throw new BusinessException("已有报价,请勿重复报价!"); } DomainAsk domainAsk = DomainAsk.builder() .domainOrderId(domainOrderId) .assetId(asset.getId()) .name(domainOrder.getDomainName()) .ownerAvatar(asset.getOwnerAvatar()) .ownerId(asset.getOwnerId()) .nickname(user.getNickname()) .avatar(user.getAvatar()) .price(price) .userId(userId) .status(DomainAskStatus.NOT_PAID) .ownerName(asset.getOwner()) .pic(domainOrder.getPic()) .picUrl(domainOrder.getPic().get(0).getUrl()) .serviceCharge(assetService.getDomainServiceCharge(asset.getUserId())) .royalties(asset.getRoyalties()) .endTime(domainOrder.getEndTime()) .build(); return domainAskRepo.save(domainAsk); } public void notifyOrder(Long id, PayMethod payMethod, String transactionId) { DomainAsk domainAsk = domainAskRepo.findById(id).orElseThrow(new BusinessException("未找到账户")); domainAsk.setStatus(DomainAskStatus.ASKING); domainAsk.setPayMethod(payMethod); domainAsk.setTransactionId(transactionId); domainAskRepo.save(domainAsk); } public List> getGroups() { Long userId = SecurityUtils.getAuthenticatedUser().getId(); return domainAskRepo.askGroup(userId); } public void cancel(DomainAsk domainAsk) { // DomainAsk domainAsk = domainAskRepo.findById(id).orElseThrow(new BusinessException("未找到账户")); if (domainAsk.getStatus() == DomainAskStatus.NOT_PAID) { domainAsk.setStatus(DomainAskStatus.CANCELLED); } if (domainAsk.getStatus() == DomainAskStatus.ASKING) { if (!SecurityUtils.getAuthenticatedUser().getId().equals(domainAsk.getUserId())) { throw new BusinessException("该叫价用户id不匹配,不能取消"); } domainAsk.setStatus(DomainAskStatus.REFUNDED); refund(domainAsk); } domainAskRepo.save(domainAsk); } public void refund(DomainAsk domainAsk) { userBalanceService .addBalance(domainAsk.getUserId(), domainAsk.getPrice(), domainAsk.getId(), BalanceType.REFUND); } public void accept(Long id) { DomainAsk domainAsk = domainAskRepo.findById(id).orElseThrow(new BusinessException("未查询到该叫价订单")); Asset asset = assetRepo.findById(domainAsk.getAssetId()).orElseThrow(new BusinessException("未找到该藏品")); if (!SecurityUtils.getAuthenticatedUser().getId().equals(domainAsk.getOwnerId())) { throw new BusinessException("非本人收到的报价,不可确认"); } if (!domainAsk.getStatus().equals(DomainAskStatus.ASKING)) { throw new BusinessException("该报价未在正在报价状态"); } Set domainAskStatuses = new HashSet<>(); domainAskStatuses.add(DomainAskStatus.FINISH); if (domainAskRepo .countByAssetIdAndOwnerIdAndStatusInAndDelFalse(asset.getId(), domainAsk .getOwnerId(), domainAskStatuses) > 0) { throw new BusinessException("已有通过报价,请勿重复通过!"); } BigDecimal amount = domainAsk.getPrice() // .subtract(BigDecimal.valueOf(1)) .multiply(BigDecimal .valueOf(100 - domainAsk.getRoyalties() - domainAsk.getServiceCharge())) .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP); assetService.transfer(asset, amount, userRepo.findById(domainAsk.getUserId()) .orElseThrow(new BusinessException("未找到用户")), TransferReason.ASK, domainAsk .getId()); userBalanceService.realtimeSettleOrder(domainAsk); domainAsk.setStatus(DomainAskStatus.FINISH); domainAskRepo.save(domainAsk); List otherAsks = domainAskRepo .findByAssetIdAndStatusAndDelFalse(asset.getId(), DomainAskStatus.ASKING); otherAsks.forEach(this::cancel); } }