Commit a0601766 authored by shiyu's avatar shiyu

藏家订单加锁避免重复创建订单

parent 9a04e972
......@@ -384,138 +384,146 @@ public class DistributionOrderServiceImpl implements DistributionOrderService {
@Override
@Transactional
public Result createCollectionOrder(DistributionOrderRequestDto dto) {
Long itemId = dto.getItemId();
String itemIdKey = "COLLECTION:ORDER:CREATE:" + dto.getItemId();
RLock lock = redissonClient.getLock(itemIdKey);
try {
Long itemId = dto.getItemId();
String shareRecordId = dto.getShareRecordId();
if (StringUtils.hasLength(shareRecordId)) {
//查询分享记录详细信息
CollectionShareRecord collectionShareRecord = collectionShareRecordDao.findById(shareRecordId);
if (collectionShareRecord == null || collectionShareRecord.getType() == DistributionEnum.CollectionShareTypeEnum.PAGE.getCode()) {
return Result.failed("该分享链接无效");
if (lock.tryLock(3, 3, TimeUnit.SECONDS)) {
String shareRecordId = dto.getShareRecordId();
if (StringUtils.hasLength(shareRecordId)) {
//查询分享记录详细信息
CollectionShareRecord collectionShareRecord = collectionShareRecordDao.findById(shareRecordId);
if (collectionShareRecord == null || collectionShareRecord.getType() == DistributionEnum.CollectionShareTypeEnum.PAGE.getCode()) {
return Result.failed("该分享链接无效");
}
if (collectionShareRecord.getIsDeleted()) {
return Result.failed("该分享链接已失效");
}
itemId = collectionShareRecord.getShareTargetId();
}
if (collectionShareRecord.getIsDeleted()) {
return Result.failed("该分享链接已失效");
//查询商品信息,检查商品库存
SupplierItem supplierItem = supplierItemDao.findById(itemId);
int stock = supplierItem.getStock();
if (stock <= 0) {
return Result.failed("商品库存不足");
}
//商品限购数量
if (dto.getItemNum() > stock) {
return Result.failed("超出库存");
}
//商品限购数量
int buyLimitNum = supplierItem.getBuyLimitNum() == -1 ? 9999999 : supplierItem.getBuyLimitNum();
//检查该购买者是否超出限购数量
//1.查询购买者对该商品的历史购买记录
List<DistributionOrder> distributionOrders = distributionOrderDao.findValidOrderOfItemIdByBuyerId(dto.getBuyerId(), itemId);
int buyNum = 0;
if (!CollectionUtils.isEmpty(distributionOrders)) {
buyNum = distributionOrders.stream().mapToInt(DistributionOrder::getItemNum).sum();
}
if (buyNum + dto.getItemNum() > buyLimitNum) {
return Result.failed("超出购买上限" + buyLimitNum + "件");
}
itemId = collectionShareRecord.getShareTargetId();
}
//查询商品信息,检查商品库存
SupplierItem supplierItem = supplierItemDao.findById(itemId);
int stock = supplierItem.getStock();
if (stock <= 0) {
return Result.failed("商品库存不足");
}
//商品限购数量
if (dto.getItemNum() > stock) {
return Result.failed("超出库存");
}
//商品限购数量
int buyLimitNum = supplierItem.getBuyLimitNum() == -1 ? 9999999 : supplierItem.getBuyLimitNum();
//检查该购买者是否超出限购数量
//1.查询购买者对该商品的历史购买记录
List<DistributionOrder> distributionOrders = distributionOrderDao.findValidOrderOfItemIdByBuyerId(dto.getBuyerId(), itemId);
int buyNum = 0;
if (!CollectionUtils.isEmpty(distributionOrders)) {
buyNum = distributionOrders.stream().mapToInt(DistributionOrder::getItemNum).sum();
}
if (buyNum + dto.getItemNum() > buyLimitNum) {
return Result.failed("超出购买上限" + buyLimitNum + "件");
}
String distributionOrderId = IdUtils.getOrderNumber(DISTRIBUTION_ORDER_PREFIX);
DistributionOrderRequestDto prePayDto = new DistributionOrderRequestDto();
prePayDto.setDistributionOrderId(distributionOrderId);
prePayDto.setAmount(String.valueOf(supplierItem.getDistributionPrice() * dto.getItemNum()));
prePayDto.setBuyerOpenid(dto.getBuyerOpenid());
prePayDto.setItemName(supplierItem.getName());
Result prePayResult = wxPayServiceApi.createPrepareOrder(prePayDto);
if (!prePayResult.getSuccess()) {
return Result.failed("购买藏品预下单失败");
}
String prepayId = (String) prePayResult.getData();
//查询该用户介绍人
long introducerId;
IntroduceRecord introduceRecord = introduceRecordDao.findByUserId(dto.getBuyerId());
if (introduceRecord == null) {
introducerId = CommConsts.SYSTEM_ACCOUNT;
IntroduceRecord newRecord = new IntroduceRecord();
newRecord.setUserId(dto.getBuyerId());
newRecord.setIntroducerId(introducerId);
newRecord.setShareRecordId(CommConsts.DEFAULT_SHARE_ID);
newRecord.setCreateTime(new Date());
introduceRecordDao.insert(newRecord);
} else {
introducerId = introduceRecord.getIntroducerId();
}
//查询佣金比例
double rebate = distributorProfitService.getIntroduceRebate(dto.getBuyerId(), introducerId);
DistributionOrder distributionOrder = new DistributionOrder();
distributionOrder.setIntroduceRebate(BigDecimal.valueOf(rebate));
distributionOrder.setIntroducerId(introducerId);
distributionOrder.setItemId(itemId);
distributionOrder.setItemNum(dto.getItemNum());
distributionOrder.setShareRecordId(String.valueOf(introducerId));
distributionOrder.setDistributionOrderId(distributionOrderId);
distributionOrder.setPrepayId(prepayId);
distributionOrder.setBuyerId(dto.getBuyerId());
distributionOrder.setBuyerOpenid(dto.getBuyerOpenid());
distributionOrder.setShopId(supplierItem.getCreatorId());
distributionOrder.setSellerId(supplierItem.getCreatorId());
distributionOrder.setAmount(supplierItem.getDistributionPrice() * dto.getItemNum());
distributionOrder.setAddressId(dto.getAddressId());
distributionOrder.setReceiverAddress(dto.getReceiverAddress());
distributionOrder.setReceiverName(dto.getReceiverName());
distributionOrder.setReceiverPhone(dto.getReceiverPhone());
distributionOrder.setCreateTime(new Date());
distributionOrder.setUpdateTime(new Date());
distributionOrder.setType(DistributionEnum.DistributionTypeEnum.COLLECT.getCode());
distributionOrder.setState(DistributionEnum.DistributionOrderStateEnum.PRE_PAY.getCode());
distributionOrderDao.insert(distributionOrder);
Map<String, String> map = new HashMap<>();
map.put("distributionOrderId", distributionOrderId);
map.put("prepayId", prepayId);
//计算分销商的利润
DistributorProfit distributorProfit = new DistributorProfit();
//平台服务费,默认15%
CollectorWhiteList collectorWhiteList = collectorWhiteListDao.findById(supplierItem.getCreatorId());
double channelCostRebate = 0.15;
if (collectorWhiteList != null && collectorWhiteList.getChannelCostRebate() != null) {
BigDecimal channelCost = collectorWhiteList.getChannelCostRebate();
channelCost = PriceUtil.convertToDivide(channelCost);
channelCostRebate = channelCost.doubleValue();
}
logger.info("藏家id:{} 生成新订单,平台服务费比例:{}", supplierItem.getCreatorId(), channelCostRebate);
String distributionOrderId = IdUtils.getOrderNumber(DISTRIBUTION_ORDER_PREFIX);
DistributionOrderRequestDto prePayDto = new DistributionOrderRequestDto();
prePayDto.setDistributionOrderId(distributionOrderId);
prePayDto.setAmount(String.valueOf(supplierItem.getDistributionPrice() * dto.getItemNum()));
prePayDto.setBuyerOpenid(dto.getBuyerOpenid());
prePayDto.setItemName(supplierItem.getName());
Result prePayResult = wxPayServiceApi.createPrepareOrder(prePayDto);
if (!prePayResult.getSuccess()) {
return Result.failed("购买藏品预下单失败");
}
String prepayId = (String) prePayResult.getData();
//实际订单到账金额
double realAmount = distributionOrder.getAmount().doubleValue() * (1 - CommConsts.WX_COMMISSION_REBATE);
//查询该用户介绍人
long introducerId;
IntroduceRecord introduceRecord = introduceRecordDao.findByUserId(dto.getBuyerId());
if (introduceRecord == null) {
introducerId = CommConsts.SYSTEM_ACCOUNT;
IntroduceRecord newRecord = new IntroduceRecord();
newRecord.setUserId(dto.getBuyerId());
newRecord.setIntroducerId(introducerId);
newRecord.setShareRecordId(CommConsts.DEFAULT_SHARE_ID);
newRecord.setCreateTime(new Date());
introduceRecordDao.insert(newRecord);
} else {
introducerId = introduceRecord.getIntroducerId();
}
//查询佣金比例
double rebate = distributorProfitService.getIntroduceRebate(dto.getBuyerId(), introducerId);
//平台佣金还要减去微信的服务手续费1%,实际上平台佣金就是订单金额* (平台佣金比例(默认0.15)- 微信手续费(0.01))
//暂时先不考虑
double channelServiceCost = distributionOrder.getAmount().doubleValue() * channelCostRebate;
DistributionOrder distributionOrder = new DistributionOrder();
distributionOrder.setIntroduceRebate(BigDecimal.valueOf(rebate));
distributionOrder.setIntroducerId(introducerId);
distributionOrder.setItemId(itemId);
distributionOrder.setItemNum(dto.getItemNum());
distributionOrder.setShareRecordId(String.valueOf(introducerId));
distributionOrder.setDistributionOrderId(distributionOrderId);
distributionOrder.setPrepayId(prepayId);
distributionOrder.setBuyerId(dto.getBuyerId());
distributionOrder.setBuyerOpenid(dto.getBuyerOpenid());
distributionOrder.setShopId(supplierItem.getCreatorId());
distributionOrder.setSellerId(supplierItem.getCreatorId());
distributionOrder.setAmount(supplierItem.getDistributionPrice() * dto.getItemNum());
distributionOrder.setAddressId(dto.getAddressId());
distributionOrder.setReceiverAddress(dto.getReceiverAddress());
distributionOrder.setReceiverName(dto.getReceiverName());
distributionOrder.setReceiverPhone(dto.getReceiverPhone());
distributionOrder.setCreateTime(new Date());
distributionOrder.setUpdateTime(new Date());
distributionOrder.setType(DistributionEnum.DistributionTypeEnum.COLLECT.getCode());
distributionOrder.setState(DistributionEnum.DistributionOrderStateEnum.PRE_PAY.getCode());
distributionOrderDao.insert(distributionOrder);
Map<String, String> map = new HashMap<>();
map.put("distributionOrderId", distributionOrderId);
map.put("prepayId", prepayId);
//计算分销商的利润
DistributorProfit distributorProfit = new DistributorProfit();
//平台服务费,默认15%
CollectorWhiteList collectorWhiteList = collectorWhiteListDao.findById(supplierItem.getCreatorId());
double channelCostRebate = 0.15;
if (collectorWhiteList != null && collectorWhiteList.getChannelCostRebate() != null) {
BigDecimal channelCost = collectorWhiteList.getChannelCostRebate();
channelCost = PriceUtil.convertToDivide(channelCost);
channelCostRebate = channelCost.doubleValue();
}
logger.info("藏家id:{} 生成新订单,平台服务费比例:{}", supplierItem.getCreatorId(), channelCostRebate);
//实际订单到账金额
double realAmount = distributionOrder.getAmount().doubleValue() * (1 - CommConsts.WX_COMMISSION_REBATE);
double introduceCost = distributionOrder.getAmount().doubleValue() * rebate;
distributorProfit.setDistributionOrderId(distributionOrderId);
distributorProfit.setDistributorId(distributionOrder.getSellerId());
distributorProfit.setItemId(distributionOrder.getItemId());
distributorProfit.setItemNum(distributionOrder.getItemNum());
distributorProfit.setAmount(distributionOrder.getAmount());
distributorProfit.setRealAmount(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(realAmount)));
distributorProfit.setItemCost(supplierItem.getSupplyPrice());
distributorProfit.setChannelCost(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(channelServiceCost)));
distributorProfit.setIntroduceCost(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(introduceCost)));
long profit = distributionOrder.getAmount() - distributorProfit.getChannelCost() - distributorProfit.getIntroduceCost();
distributorProfit.setProfit(profit);
distributorProfit.setCreateTime(new Date());
distributorProfit.setIsValid(false);
distributorProfit.setType(DistributionEnum.DistributionTypeEnum.COLLECT.getCode());
distributorProfitDao.insert(distributorProfit);
return Result.success(map);
//平台佣金还要减去微信的服务手续费1%,实际上平台佣金就是订单金额* (平台佣金比例(默认0.15)- 微信手续费(0.01))
//暂时先不考虑
double channelServiceCost = distributionOrder.getAmount().doubleValue() * channelCostRebate;
double introduceCost = distributionOrder.getAmount().doubleValue() * rebate;
distributorProfit.setDistributionOrderId(distributionOrderId);
distributorProfit.setDistributorId(distributionOrder.getSellerId());
distributorProfit.setItemId(distributionOrder.getItemId());
distributorProfit.setItemNum(distributionOrder.getItemNum());
distributorProfit.setAmount(distributionOrder.getAmount());
distributorProfit.setRealAmount(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(realAmount)));
distributorProfit.setItemCost(supplierItem.getSupplyPrice());
distributorProfit.setChannelCost(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(channelServiceCost)));
distributorProfit.setIntroduceCost(PriceUtil.convertPriceFromStr(PriceUtil.convertDoubleToString(introduceCost)));
long profit = distributionOrder.getAmount() - distributorProfit.getChannelCost() - distributorProfit.getIntroduceCost();
distributorProfit.setProfit(profit);
distributorProfit.setCreateTime(new Date());
distributorProfit.setIsValid(false);
distributorProfit.setType(DistributionEnum.DistributionTypeEnum.COLLECT.getCode());
distributorProfitDao.insert(distributorProfit);
return Result.success(map);
} else {
return Result.failed("请勿重复提交");
}
} catch (Exception e) {
logger.error("创建藏品一口价订单失败 error : {}", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return Result.failed("藏品一口价订单下单失败");
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment