|
|
@@ -24,6 +24,7 @@ import com.izouma.nineth.domain.*;
|
|
|
import com.izouma.nineth.dto.PageQuery;
|
|
|
import com.izouma.nineth.enums.*;
|
|
|
import com.izouma.nineth.event.CreateAssetEvent;
|
|
|
+import com.izouma.nineth.event.CreateOrderEvent;
|
|
|
import com.izouma.nineth.event.TransferAssetEvent;
|
|
|
import com.izouma.nineth.exception.BusinessException;
|
|
|
import com.izouma.nineth.repo.*;
|
|
|
@@ -36,10 +37,11 @@ import org.apache.commons.codec.EncoderException;
|
|
|
import org.apache.commons.codec.net.URLCodec;
|
|
|
import org.apache.commons.collections.MapUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.rocketmq.client.producer.SendResult;
|
|
|
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
|
|
import org.springframework.context.event.EventListener;
|
|
|
import org.springframework.core.env.Environment;
|
|
|
import org.springframework.data.domain.Page;
|
|
|
-import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.ui.Model;
|
|
|
@@ -56,135 +58,146 @@ import java.util.*;
|
|
|
@Slf4j
|
|
|
public class OrderService {
|
|
|
|
|
|
- private OrderRepo orderRepo;
|
|
|
- private CollectionRepo collectionRepo;
|
|
|
- private UserAddressRepo userAddressRepo;
|
|
|
- private UserRepo userRepo;
|
|
|
- private Environment env;
|
|
|
- private AlipayClient alipayClient;
|
|
|
- private AlipayProperties alipayProperties;
|
|
|
- private WxPayService wxPayService;
|
|
|
- private WxPayProperties wxPayProperties;
|
|
|
- private AssetService assetService;
|
|
|
- private SysConfigService sysConfigService;
|
|
|
- private BlindBoxItemRepo blindBoxItemRepo;
|
|
|
- private AssetRepo assetRepo;
|
|
|
- private UserCouponRepo userCouponRepo;
|
|
|
- private CollectionService collectionService;
|
|
|
- private RedisTemplate<String, Object> redisTemplate;
|
|
|
- private CommissionRecordRepo commissionRecordRepo;
|
|
|
- private AdapayProperties adapayProperties;
|
|
|
- private GeneralProperties generalProperties;
|
|
|
+ private OrderRepo orderRepo;
|
|
|
+ private CollectionRepo collectionRepo;
|
|
|
+ private UserAddressRepo userAddressRepo;
|
|
|
+ private UserRepo userRepo;
|
|
|
+ private Environment env;
|
|
|
+ private AlipayClient alipayClient;
|
|
|
+ private AlipayProperties alipayProperties;
|
|
|
+ private WxPayService wxPayService;
|
|
|
+ private WxPayProperties wxPayProperties;
|
|
|
+ private AssetService assetService;
|
|
|
+ private SysConfigService sysConfigService;
|
|
|
+ private BlindBoxItemRepo blindBoxItemRepo;
|
|
|
+ private AssetRepo assetRepo;
|
|
|
+ private UserCouponRepo userCouponRepo;
|
|
|
+ private CollectionService collectionService;
|
|
|
+ private CommissionRecordRepo commissionRecordRepo;
|
|
|
+ private AdapayProperties adapayProperties;
|
|
|
+ private GeneralProperties generalProperties;
|
|
|
+ private RocketMQTemplate rocketMQTemplate;
|
|
|
|
|
|
public Page<Order> all(PageQuery pageQuery) {
|
|
|
return orderRepo.findAll(JpaUtils.toSpecification(pageQuery, Order.class), JpaUtils.toPageRequest(pageQuery));
|
|
|
}
|
|
|
|
|
|
+ public Object mqCreate(Long userId, Long collectionId, int qty, Long addressId, Long userCouponId, Long invitor) {
|
|
|
+ SendResult result = rocketMQTemplate.syncSend("create-order", new CreateOrderEvent(userId, collectionId, qty, addressId, userCouponId, invitor));
|
|
|
+ return result.getMsgId();
|
|
|
+ }
|
|
|
+
|
|
|
@Transactional
|
|
|
public Order create(Long userId, Long collectionId, int qty, Long addressId, Long userCouponId, Long invitor) {
|
|
|
- if (qty <= 0) throw new BusinessException("数量必须大于0");
|
|
|
- Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("藏品不存在"));
|
|
|
- User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("铸造者不存在"));
|
|
|
- UserCoupon coupon = null;
|
|
|
- if (userCouponId != null) {
|
|
|
- coupon = userCouponRepo.findById(userCouponId).orElseThrow(new BusinessException("兑换券不存在"));
|
|
|
- if (coupon.isUsed()) {
|
|
|
- throw new BusinessException("该兑换券已使用");
|
|
|
+ qty = 1;
|
|
|
+ int stock = Optional.ofNullable(collectionService.decreaseStock(collectionId, qty))
|
|
|
+ .map(Math::toIntExact)
|
|
|
+ .orElseThrow(new BusinessException("很遗憾,藏品已售罄"));
|
|
|
+ try {
|
|
|
+ if (stock < 0) {
|
|
|
+ throw new BusinessException("很遗憾,藏品已售罄");
|
|
|
}
|
|
|
- if (coupon.isLimited() && !coupon.getCollectionIds().contains(collectionId)) {
|
|
|
- throw new BusinessException("该兑换券不可用");
|
|
|
+ Collection collection = collectionRepo.findById(collectionId).orElseThrow(new BusinessException("藏品不存在"));
|
|
|
+ User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("铸造者不存在"));
|
|
|
+ UserCoupon coupon = null;
|
|
|
+ if (userCouponId != null) {
|
|
|
+ coupon = userCouponRepo.findById(userCouponId).orElseThrow(new BusinessException("兑换券不存在"));
|
|
|
+ if (coupon.isUsed()) {
|
|
|
+ throw new BusinessException("该兑换券已使用");
|
|
|
+ }
|
|
|
+ if (coupon.isLimited() && !coupon.getCollectionIds().contains(collectionId)) {
|
|
|
+ throw new BusinessException("该兑换券不可用");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- if (collection.isScheduleSale()) {
|
|
|
- if (collection.getStartTime().isAfter(LocalDateTime.now())) {
|
|
|
- throw new BusinessException("当前还未开售");
|
|
|
+ if (collection.isScheduleSale()) {
|
|
|
+ if (collection.getStartTime().isAfter(LocalDateTime.now())) {
|
|
|
+ throw new BusinessException("当前还未开售");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- if (!collection.isSalable()) {
|
|
|
- throw new BusinessException("该藏品当前不可购买");
|
|
|
- }
|
|
|
- if (!collection.isOnShelf()) {
|
|
|
- if (!collection.isScanCode()) {
|
|
|
- throw new BusinessException("藏品已下架");
|
|
|
+ if (!collection.isOnShelf()) {
|
|
|
+ if (!collection.isScanCode()) {
|
|
|
+ throw new BusinessException("藏品已下架");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- if (qty > collection.getStock()) {
|
|
|
- throw new BusinessException("库存不足");
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
- if (collection.getMaxCount() > 0) {
|
|
|
- int count;
|
|
|
- if (StringUtils.isNotBlank(collection.getCountId())) {
|
|
|
- count = orderRepo.countByUserIdAndCountIdAndStatusIn(userId, collection.getCountId(), Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
|
|
|
- } else {
|
|
|
- count = orderRepo.countByUserIdAndCollectionIdAndStatusIn(userId, collectionId, Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
|
|
|
+ if (!collection.isSalable()) {
|
|
|
+ throw new BusinessException("该藏品当前不可购买");
|
|
|
}
|
|
|
- if (count >= collection.getMaxCount()) {
|
|
|
- throw new BusinessException("限购" + collection.getMaxCount() + "件");
|
|
|
+
|
|
|
+ if (collection.getMaxCount() > 0) {
|
|
|
+ int count;
|
|
|
+ if (StringUtils.isNotBlank(collection.getCountId())) {
|
|
|
+ count = orderRepo.countByUserIdAndCountIdAndStatusIn(userId, collection.getCountId(), Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
|
|
|
+ } else {
|
|
|
+ count = orderRepo.countByUserIdAndCollectionIdAndStatusIn(userId, collectionId, Arrays.asList(OrderStatus.FINISH, OrderStatus.NOT_PAID, OrderStatus.PROCESSING));
|
|
|
+ }
|
|
|
+ if (count >= collection.getMaxCount()) {
|
|
|
+ throw new BusinessException("限购" + collection.getMaxCount() + "件");
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- UserAddress userAddress = null;
|
|
|
- if (addressId != null) {
|
|
|
- userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
|
|
|
- }
|
|
|
+ UserAddress userAddress = null;
|
|
|
+ if (addressId != null) {
|
|
|
+ userAddress = userAddressRepo.findById(addressId).orElseThrow(new BusinessException("地址信息不存在"));
|
|
|
+ }
|
|
|
|
|
|
- collectionRepo.increaseStock(collectionId, -qty);
|
|
|
- collectionRepo.increaseSale(collectionId, qty);
|
|
|
-
|
|
|
- BigDecimal gasFee = sysConfigService.getBigDecimal("gas_fee");
|
|
|
- Order order = Order.builder()
|
|
|
- .userId(userId)
|
|
|
- .collectionId(collectionId)
|
|
|
- .name(collection.getName())
|
|
|
- .pic(collection.getPic())
|
|
|
- .detail(collection.getDetail())
|
|
|
- .properties(collection.getProperties())
|
|
|
- .category(collection.getCategory())
|
|
|
- .canResale(collection.isCanResale())
|
|
|
- .royalties(collection.getRoyalties())
|
|
|
- .serviceCharge(collection.getServiceCharge())
|
|
|
- .type(collection.getType())
|
|
|
- .minterId(collection.getMinterId())
|
|
|
- .minter(minter.getNickname())
|
|
|
- .minterAvatar(minter.getAvatar())
|
|
|
- .qty(qty)
|
|
|
- .price(collection.getPrice())
|
|
|
- .gasPrice(gasFee)
|
|
|
- .totalPrice(collection.getPrice().multiply(BigDecimal.valueOf(qty)).add(gasFee))
|
|
|
- .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
|
|
|
- .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
|
|
|
- .address(Optional.ofNullable(userAddress).map(u ->
|
|
|
- u.getProvinceId() + " " + u.getCityId() + " " + u.getDistrictId() + " " + u.getAddress())
|
|
|
- .orElse(null))
|
|
|
- .status(OrderStatus.NOT_PAID)
|
|
|
- .assetId(collection.getAssetId())
|
|
|
- .couponId(userCouponId)
|
|
|
- .invitor(invitor)
|
|
|
- .countId(collection.getCountId())
|
|
|
- .build();
|
|
|
- if (coupon != null) {
|
|
|
- coupon.setUsed(true);
|
|
|
- coupon.setUseTime(LocalDateTime.now());
|
|
|
- if (coupon.isNeedGas()) {
|
|
|
- order.setTotalPrice(order.getGasPrice());
|
|
|
- } else {
|
|
|
- order.setTotalPrice(BigDecimal.ZERO);
|
|
|
+ BigDecimal gasFee = sysConfigService.getBigDecimal("gas_fee");
|
|
|
+ Order order = Order.builder()
|
|
|
+ .userId(userId)
|
|
|
+ .collectionId(collectionId)
|
|
|
+ .name(collection.getName())
|
|
|
+ .pic(collection.getPic())
|
|
|
+ .detail(collection.getDetail())
|
|
|
+ .properties(collection.getProperties())
|
|
|
+ .category(collection.getCategory())
|
|
|
+ .canResale(collection.isCanResale())
|
|
|
+ .royalties(collection.getRoyalties())
|
|
|
+ .serviceCharge(collection.getServiceCharge())
|
|
|
+ .type(collection.getType())
|
|
|
+ .source(collection.getSource())
|
|
|
+ .minterId(collection.getMinterId())
|
|
|
+ .minter(minter.getNickname())
|
|
|
+ .minterAvatar(minter.getAvatar())
|
|
|
+ .qty(qty)
|
|
|
+ .price(collection.getPrice())
|
|
|
+ .gasPrice(gasFee)
|
|
|
+ .totalPrice(collection.getPrice().multiply(BigDecimal.valueOf(qty)).add(gasFee))
|
|
|
+ .contactName(Optional.ofNullable(userAddress).map(UserAddress::getName).orElse(null))
|
|
|
+ .contactPhone(Optional.ofNullable(userAddress).map(UserAddress::getPhone).orElse(null))
|
|
|
+ .address(Optional.ofNullable(userAddress).map(u ->
|
|
|
+ u.getProvinceId() + " " + u.getCityId() + " " + u.getDistrictId() + " " + u.getAddress())
|
|
|
+ .orElse(null))
|
|
|
+ .status(OrderStatus.NOT_PAID)
|
|
|
+ .assetId(collection.getAssetId())
|
|
|
+ .couponId(userCouponId)
|
|
|
+ .invitor(invitor)
|
|
|
+ .countId(collection.getCountId())
|
|
|
+ .build();
|
|
|
+ if (coupon != null) {
|
|
|
+ coupon.setUsed(true);
|
|
|
+ coupon.setUseTime(LocalDateTime.now());
|
|
|
+ if (coupon.isNeedGas()) {
|
|
|
+ order.setTotalPrice(order.getGasPrice());
|
|
|
+ } else {
|
|
|
+ order.setTotalPrice(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (collection.getSource() == CollectionSource.TRANSFER) {
|
|
|
- Asset asset = assetRepo.findById(collection.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
- asset.setStatus(AssetStatus.TRADING);
|
|
|
- assetRepo.save(asset);
|
|
|
- collectionRepo.setOnShelf(collectionId, false);
|
|
|
- }
|
|
|
- order = orderRepo.save(order);
|
|
|
- if (order.getTotalPrice().equals(BigDecimal.ZERO)) {
|
|
|
- notifyOrder(order.getId(), PayMethod.WEIXIN, null);
|
|
|
+ if (collection.getSource() == CollectionSource.TRANSFER) {
|
|
|
+ Asset asset = assetRepo.findById(collection.getAssetId()).orElseThrow(new BusinessException("资产不存在"));
|
|
|
+ asset.setStatus(AssetStatus.TRADING);
|
|
|
+ assetRepo.save(asset);
|
|
|
+ collectionRepo.setOnShelf(collectionId, false);
|
|
|
+ }
|
|
|
+ order = orderRepo.save(order);
|
|
|
+ if (order.getTotalPrice().equals(BigDecimal.ZERO)) {
|
|
|
+ notifyOrder(order.getId(), PayMethod.WEIXIN, null);
|
|
|
+ }
|
|
|
+ return order;
|
|
|
+ } catch (Exception e) {
|
|
|
+ collectionService.increaseStock(collectionId, qty);
|
|
|
+ throw e;
|
|
|
}
|
|
|
- return order;
|
|
|
}
|
|
|
|
|
|
public void payOrderAlipay(Long id, Model model) {
|
|
|
@@ -461,20 +474,20 @@ public class OrderService {
|
|
|
if (order.getStatus() != OrderStatus.NOT_PAID) {
|
|
|
throw new BusinessException("已支付订单无法取消");
|
|
|
}
|
|
|
- Collection collection = collectionRepo.findById(order.getCollectionId())
|
|
|
- .orElseThrow(new BusinessException("藏品不存在"));
|
|
|
- User minter = userRepo.findById(collection.getMinterId()).orElseThrow(new BusinessException("铸造者不存在"));
|
|
|
|
|
|
- if (collection.getSource() == CollectionSource.TRANSFER) {
|
|
|
- Asset asset = assetRepo.findById(collection.getAssetId()).orElse(null);
|
|
|
+ CollectionSource source = Optional.ofNullable(order.getSource()).orElseGet(() ->
|
|
|
+ collectionRepo.findById(order.getCollectionId()).map(Collection::getSource).orElse(null));
|
|
|
+
|
|
|
+ if (source == CollectionSource.TRANSFER) {
|
|
|
+ Asset asset = assetRepo.findById(order.getAssetId()).orElse(null);
|
|
|
if (asset != null) {
|
|
|
asset.setStatus(AssetStatus.NORMAL);
|
|
|
assetRepo.save(asset);
|
|
|
}
|
|
|
- collectionRepo.setOnShelf(collection.getId(), true);
|
|
|
+ collectionRepo.setOnShelf(order.getCollectionId(), true);
|
|
|
}
|
|
|
- collectionRepo.increaseSale(collection.getId(), -order.getQty());
|
|
|
- collectionRepo.increaseStock(collection.getId(), order.getQty());
|
|
|
+ collectionService.decreaseStock(order.getCollectionId(), order.getQty());
|
|
|
+ collectionService.increaseSale(order.getCollectionId(), order.getQty());
|
|
|
|
|
|
order.setStatus(OrderStatus.CANCELLED);
|
|
|
order.setCancelTime(LocalDateTime.now());
|