package cc.mrbird.febs.mall.service.impl;
|
|
import cc.mrbird.febs.common.entity.FebsResponse;
|
import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
|
import cc.mrbird.febs.common.enumerates.FlowTypeNewEnum;
|
import cc.mrbird.febs.common.enumerates.MoneyFlowTypeNewEnum;
|
import cc.mrbird.febs.common.enumerates.ProductEnum;
|
import cc.mrbird.febs.common.exception.FebsException;
|
import cc.mrbird.febs.common.utils.LoginUserUtil;
|
import cc.mrbird.febs.common.utils.MallUtils;
|
import cc.mrbird.febs.mall.dto.ApiCreateNFTDto;
|
import cc.mrbird.febs.mall.dto.ApiOutFcmDto;
|
import cc.mrbird.febs.mall.dto.ApiOutNFTDto;
|
import cc.mrbird.febs.mall.entity.*;
|
import cc.mrbird.febs.mall.mapper.*;
|
import cc.mrbird.febs.mall.service.IApiMallProductService;
|
import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
|
import cc.mrbird.febs.mall.vo.ApiMallProductNftVo;
|
import cc.mrbird.febs.rabbit.producter.AgentProducer;
|
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.crypto.SecureUtil;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.math.BigDecimal;
|
import java.util.List;
|
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class ApiMallProductServiceImpl extends ServiceImpl<MallProductNftMapper, MallProductNft> implements IApiMallProductService {
|
|
private final MallMemberMapper memberMapper;
|
private final MallProductBuyMapper mallProductBuyMapper;
|
private final MallMemberAmountMapper mallMemberAmountMapper;
|
private final IMallMoneyFlowService iMallMoneyFlowService;
|
private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
|
private final AgentProducer agentProducer;
|
private final MallProductSellMapper mallProductSellMapper;
|
private final MallProductSellRecordMapper mallProductSellRecordMapper;
|
|
@Override
|
public List<ApiMallProductNftVo> productNFTList() {
|
List<ApiMallProductNftVo> list = this.baseMapper.selectByState(ProductEnum.PRODUCT_NFT_OPEN.getValue());
|
return list;
|
}
|
|
@Override
|
@Transactional
|
public FebsResponse createNFT(ApiCreateNFTDto createNFTDto) {
|
Long memberId = LoginUserUtil.getLoginUser().getId();
|
MallMember mallMember = memberMapper.selectById(memberId);
|
Long productNFTId = createNFTDto.getId();
|
String tradePassword = SecureUtil.md5(createNFTDto.getTradePassword());
|
/**
|
* 预约,验证交易密码、预约产品是否开启状态、该产品是否已经预约、token是否足够
|
* 冻结对应的令牌数量、生成预约记录、生成流水记录
|
*/
|
if(!tradePassword.equals(mallMember.getTradePassword())){
|
throw new FebsException("请输入正确的交易密码");
|
}
|
MallProductNft mallProductNft = this.baseMapper.selectById(productNFTId);
|
if(ObjectUtil.isEmpty(mallProductNft)){
|
throw new FebsException("网络异常");
|
}
|
if(ProductEnum.PRODUCT_NFT_OPEN.getValue() != mallProductNft.getState()){
|
throw new FebsException("预约超时");
|
}
|
MallProductBuy mallProductBuy = mallProductBuyMapper.selectMemberIdAndNFTIdAndStateAndMateState(
|
memberId,productNFTId,ProductEnum.PRODUCT_BUY_ON_GOING.getValue(),null);
|
if(ObjectUtil.isNotEmpty(mallProductBuy)){
|
throw new FebsException("不可重复预约");
|
}
|
|
BigDecimal priceToken = mallProductNft.getPriceToken();
|
MallMemberAmount mallMemberAmount = mallMemberAmountMapper.selectByMemberId(memberId);
|
if(BigDecimal.ZERO.compareTo(mallMemberAmount.getTokenAva()) >= 0
|
|| priceToken.compareTo(mallMemberAmount.getTokenAva()) > 0){
|
throw new FebsException("余额不足");
|
}
|
mallProductBuy = new MallProductBuy();
|
mallProductBuy.setMemberId(memberId);
|
mallProductBuy.setProductNftId(mallProductNft.getId());
|
mallProductBuy.setState(ProductEnum.PRODUCT_BUY_ON_GOING.getValue());
|
mallProductBuy.setMateState(ProductEnum.PRODUCT_MATE_STATE_ON_GOING.getValue());
|
mallProductBuy.setNftTotal(mallProductNft.getPriceNft());
|
mallProductBuy.setNftAva(BigDecimal.ZERO);
|
mallProductBuyMapper.insert(mallProductBuy);
|
//令牌 可用减少,冻结增加
|
mallMemberAmount.setTokenAva(mallMemberAmount.getTokenAva().subtract(priceToken));
|
mallMemberAmount.setTokenFrozen(mallMemberAmount.getTokenFrozen().add(priceToken));
|
mallMemberAmountMapper.updateTokenAvaAndTokenFrozenById(mallMemberAmount);
|
|
String orderNo = MallUtils.getOrderNum("YY");
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
priceToken.negate(),
|
MoneyFlowTypeNewEnum.TOKEN_BUY_FROZEN.getValue(),
|
orderNo,
|
null,
|
FlowTypeNewEnum.TOKEN.getValue(),
|
MoneyFlowTypeNewEnum.TOKEN_BUY_FROZEN.getDescrition());
|
return new FebsResponse().success();
|
}
|
|
@Override
|
@Transactional
|
public FebsResponse outFcm(ApiOutFcmDto outFcmDto) {
|
Long memberId = LoginUserUtil.getLoginUser().getId();
|
MallMember mallMember = memberMapper.selectById(memberId);
|
String tradePassword = SecureUtil.md5(outFcmDto.getTradePassword());
|
/**
|
* 实时兑换FCM-to-NFT
|
* 验证账户交易密码,fcm余额
|
* 计算手续费、减少用户的fcm余额
|
* 增加流水
|
*/
|
if(!tradePassword.equals(mallMember.getTradePassword())){
|
throw new FebsException("请输入正确的交易密码");
|
}
|
BigDecimal fcmCnt = outFcmDto.getFcmCnt();
|
DataDictionaryCustom outFcmMinDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.OUT_FCM_MIN.getType(),
|
DataDictionaryEnum.OUT_FCM_MIN.getCode());
|
BigDecimal outFcmMin = ObjectUtil.isEmpty(outFcmMinDic) ? new BigDecimal(100) : new BigDecimal(outFcmMinDic.getValue());
|
if(outFcmMin.compareTo(fcmCnt) > 0){
|
throw new FebsException("最少"+outFcmMin);
|
}
|
MallMemberAmount mallMemberAmount = mallMemberAmountMapper.selectByMemberId(memberId);
|
if(BigDecimal.ZERO.compareTo(mallMemberAmount.getFcmCntAva()) >= 0
|
|| fcmCnt.compareTo(mallMemberAmount.getTokenAva()) > 0){
|
throw new FebsException("余额不足");
|
}
|
DataDictionaryCustom fcmPriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.FCM_PRICE.getType(),
|
DataDictionaryEnum.FCM_PRICE.getCode());
|
BigDecimal fcmPrice = ObjectUtil.isEmpty(fcmPriceDic) ? new BigDecimal(2) : new BigDecimal(fcmPriceDic.getValue());
|
//手续费
|
DataDictionaryCustom outFcmFeeDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.OUT_FCM_FEE.getType(),
|
DataDictionaryEnum.OUT_FCM_FEE.getCode());
|
BigDecimal outFcmFeePercent = ObjectUtil.isEmpty(outFcmFeeDic) ? new BigDecimal(20) : new BigDecimal(outFcmFeeDic.getValue());
|
outFcmFeePercent = outFcmFeePercent.divide(new BigDecimal(100),4,BigDecimal.ROUND_DOWN);
|
BigDecimal outFcmFee = fcmCnt.multiply(outFcmFeePercent);
|
//实际到账数量
|
BigDecimal fcmCntReal = fcmCnt.subtract(outFcmFee).setScale(2, BigDecimal.ROUND_DOWN);
|
|
BigDecimal nftCnt = fcmCntReal.multiply(fcmPrice);
|
|
mallMemberAmount.setFcmCntAva(mallMemberAmount.getFcmCntAva().subtract(fcmCnt));
|
mallMemberAmountMapper.updateFcmCntAvaById(mallMemberAmount);
|
String orderNo = MallUtils.getOrderNum("DB");
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
fcmCnt.negate(),
|
MoneyFlowTypeNewEnum.FCM_OUT.getValue(),
|
orderNo,
|
mallMember.getId(),
|
FlowTypeNewEnum.FCM_COIN.getValue(),
|
MoneyFlowTypeNewEnum.FCM_OUT.getDescrition());
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
outFcmFee.negate(),
|
MoneyFlowTypeNewEnum.FCM_OUT_FEE.getValue(),
|
orderNo,
|
mallMember.getId(),
|
FlowTypeNewEnum.FCM_COIN.getValue(),
|
MoneyFlowTypeNewEnum.FCM_OUT_FEE.getDescrition());
|
|
mallMemberAmount.setTrendsNft(mallMemberAmount.getTrendsNft().add(nftCnt));
|
mallMemberAmountMapper.updateTrendsNftById(mallMemberAmount);
|
String orderNoNFT = MallUtils.getOrderNum("NFT");
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
nftCnt,
|
MoneyFlowTypeNewEnum.NFT_IN.getValue(),
|
orderNoNFT,
|
mallMember.getId(),
|
FlowTypeNewEnum.NFT.getValue(),
|
MoneyFlowTypeNewEnum.NFT_IN.getDescrition());
|
|
agentProducer.sendFcmNFTExchangeMsg(outFcmFee.toString());
|
return new FebsResponse().success();
|
}
|
|
@Override
|
@Transactional
|
public FebsResponse outNFT(ApiOutNFTDto outNFTDto) {
|
Long memberId = LoginUserUtil.getLoginUser().getId();
|
MallMember mallMember = memberMapper.selectById(memberId);
|
String tradePassword = SecureUtil.md5(outNFTDto.getTradePassword());
|
/**
|
* 验证数量、交易密码、NFT余额
|
* 计算手续费、减少动态NFT、增加冻结NFT
|
* 增加流水
|
*/
|
if(!tradePassword.equals(mallMember.getTradePassword())){
|
throw new FebsException("请输入正确的交易密码");
|
}
|
BigDecimal nftCnt = outNFTDto.getNftCnt();
|
DataDictionaryCustom nftMinDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.NFT_MIN.getType(),
|
DataDictionaryEnum.NFT_MIN.getCode());
|
BigDecimal nftMin = ObjectUtil.isEmpty(nftMinDic) ? new BigDecimal(100) : new BigDecimal(nftMinDic.getValue());
|
if(nftMin.compareTo(nftCnt) > 0){
|
throw new FebsException("最少"+nftMin);
|
}
|
MallMemberAmount mallMemberAmount = mallMemberAmountMapper.selectByMemberId(memberId);
|
if(BigDecimal.ZERO.compareTo(mallMemberAmount.getTrendsNft()) >= 0
|
|| nftCnt.compareTo(mallMemberAmount.getTrendsNft()) > 0){
|
throw new FebsException("余额不足");
|
}
|
DataDictionaryCustom nftFeeDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.NFT_FEE.getType(),
|
DataDictionaryEnum.NFT_FEE.getCode());
|
BigDecimal nftFeePercent = ObjectUtil.isEmpty(nftFeeDic) ? new BigDecimal(20) : new BigDecimal(nftFeeDic.getValue());
|
nftFeePercent = nftFeePercent.divide(new BigDecimal(100),4,BigDecimal.ROUND_DOWN);
|
BigDecimal nftFee = nftCnt.multiply(nftFeePercent);
|
BigDecimal nftCntAva = nftCnt.subtract(nftFee);
|
|
DataDictionaryCustom fcmPriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
|
DataDictionaryEnum.FCM_PRICE.getType(),
|
DataDictionaryEnum.FCM_PRICE.getCode());
|
BigDecimal fcmPrice = ObjectUtil.isEmpty(fcmPriceDic) ? new BigDecimal(2) : new BigDecimal(fcmPriceDic.getValue());
|
BigDecimal fcmFeeCnt = nftFee.divide(fcmPrice, 2, BigDecimal.ROUND_DOWN);
|
|
MallProductSell mallProductSell = new MallProductSell();
|
mallProductSell.setMemberId(memberId);
|
mallProductSell.setNftTotal(nftCnt);
|
mallProductSell.setNftCnt(nftCntAva);
|
mallProductSell.setNftCntAva(nftCntAva);
|
mallProductSell.setNftFee(nftFee);
|
mallProductSell.setFcmFee(fcmFeeCnt);
|
mallProductSell.setState(ProductEnum.PRODUCT_SELL_ON_GOING.getValue());
|
mallProductSellMapper.insert(mallProductSell);
|
|
mallMemberAmount.setTrendsNft(mallMemberAmount.getTrendsNft().subtract(nftCnt));
|
mallMemberAmountMapper.updateTrendsNftById(mallMemberAmount);
|
|
mallMemberAmount.setFrozenNft(mallMemberAmount.getFrozenNft().add(nftCntAva));
|
mallMemberAmountMapper.updateFrozenNftById(mallMemberAmount);
|
String orderNo = MallUtils.getOrderNum("NFT");
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
nftCnt.negate(),
|
MoneyFlowTypeNewEnum.NFT_OUT.getValue(),
|
orderNo,
|
mallMember.getId(),
|
FlowTypeNewEnum.NFT.getValue(),
|
MoneyFlowTypeNewEnum.NFT_OUT.getDescrition());
|
iMallMoneyFlowService.addMoneyFlow(
|
memberId,
|
nftFee.negate(),
|
MoneyFlowTypeNewEnum.NFT_OUT_FEE.getValue(),
|
orderNo,
|
mallMember.getId(),
|
FlowTypeNewEnum.NFT.getValue(),
|
MoneyFlowTypeNewEnum.NFT_OUT_FEE.getDescrition());
|
|
agentProducer.sendFcmNFTExchangeMsg(fcmFeeCnt.toString());
|
return new FebsResponse().success();
|
}
|
}
|