diff --git a/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/MallServerApplicationService.java b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/MallServerApplicationService.java index fc12a20..82c75f8 100644 --- a/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/MallServerApplicationService.java +++ b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/MallServerApplicationService.java @@ -2,6 +2,7 @@ package com.qniao.dam.application; import com.qniao.dam.application.request.*; import com.qniao.dam.application.response.ConsumeVirtualAccountVo; +import com.qniao.dam.application.response.CostIMGiftVo; import com.qniao.dam.application.response.UserCheckEnableRightBySdkVo; import com.qniao.dam.application.response.UserConsumeRightBySdkVo; import com.qniao.framework.annotation.IgnoreResponseAdvice; @@ -54,4 +55,8 @@ public interface MallServerApplicationService { @PostMapping("/user/acquire/reward-amount") @IgnoreResponseAdvice void userAcquireRewardAmountBySdk(@RequestBody UserAcquireRewardAmountDto dto); + + @PostMapping("/user/cost/im-gift/by/sdk") + @IgnoreResponseAdvice + CostIMGiftVo userCostIMGiftBySdk(@RequestBody UserCostIMGiftDto dto); } diff --git a/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/request/UserCostIMGiftDto.java b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/request/UserCostIMGiftDto.java new file mode 100644 index 0000000..6263142 --- /dev/null +++ b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/request/UserCostIMGiftDto.java @@ -0,0 +1,16 @@ +package com.qniao.dam.application.request; + +import lombok.Data; + +@Data +public class UserCostIMGiftDto { + + private Long fromUserId; + + private Long toUserId; + + private Long productSpecId; + + private Integer quantity; + +} diff --git a/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/response/CostIMGiftVo.java b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/response/CostIMGiftVo.java new file mode 100644 index 0000000..c2172a0 --- /dev/null +++ b/dating-agency-mall-sdk/src/main/java/com/qniao/dam/application/response/CostIMGiftVo.java @@ -0,0 +1,12 @@ +package com.qniao.dam.application.response; + +import lombok.Data; + +@Data +public class CostIMGiftVo { + + private Boolean success = false; + + private String failReason; + +} diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/VirtualAccountUserCommandController.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/VirtualAccountUserCommandController.java index 1d5f5a7..17b6d8b 100644 --- a/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/VirtualAccountUserCommandController.java +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/VirtualAccountUserCommandController.java @@ -1,6 +1,8 @@ package com.qniao.dam.api.command.virtualaccount.user; import com.qniao.dam.api.command.virtualaccount.user.request.UserConsumeVirtualAccountDto; +import com.qniao.dam.api.command.virtualaccount.user.request.UserCostIMGiftDto; +import com.qniao.dam.api.command.virtualaccount.user.response.CostIMGiftVo; import com.qniao.dam.api.command.virtualaccount.user.response.UserConsumeVirtualAccountVo; import com.qniao.dam.application.service.virtualaccount.VirtualAccountApplicationService; import com.qniao.framework.annotation.IgnoreResponseAdvice; @@ -26,4 +28,10 @@ public class VirtualAccountUserCommandController { return virtualAccountApplicationService.consume(dto); } + @PostMapping("/cost/im-gift/by/sdk") + @IgnoreResponseAdvice + public CostIMGiftVo userCostIMGiftBySdk(@RequestBody UserCostIMGiftDto dto) { + return virtualAccountApplicationService.costIMGift(dto); + } + } diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/request/UserCostIMGiftDto.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/request/UserCostIMGiftDto.java new file mode 100644 index 0000000..70d3d47 --- /dev/null +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/request/UserCostIMGiftDto.java @@ -0,0 +1,16 @@ +package com.qniao.dam.api.command.virtualaccount.user.request; + +import lombok.Data; + +@Data +public class UserCostIMGiftDto { + + private Long fromUserId; + + private Long toUserId; + + private Long productSpecId; + + private Integer quantity; + +} diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/response/CostIMGiftVo.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/response/CostIMGiftVo.java new file mode 100644 index 0000000..615ba5e --- /dev/null +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/virtualaccount/user/response/CostIMGiftVo.java @@ -0,0 +1,12 @@ +package com.qniao.dam.api.command.virtualaccount.user.response; + +import lombok.Data; + +@Data +public class CostIMGiftVo { + + private Boolean flag = false; + + private String failReason; + +} diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/virtualaccount/VirtualAccountApplicationService.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/virtualaccount/VirtualAccountApplicationService.java index 7c2b1e1..bb585a8 100644 --- a/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/virtualaccount/VirtualAccountApplicationService.java +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/virtualaccount/VirtualAccountApplicationService.java @@ -1,26 +1,44 @@ package com.qniao.dam.application.service.virtualaccount; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Tuple; import com.qniao.dam.api.command.virtualaccount.user.request.UserConsumeVirtualAccountDto; +import com.qniao.dam.api.command.virtualaccount.user.request.UserCostIMGiftDto; +import com.qniao.dam.api.command.virtualaccount.user.response.CostIMGiftVo; import com.qniao.dam.api.command.virtualaccount.user.response.UserConsumeVirtualAccountVo; import com.qniao.dam.domain.aggregate.order.entity.Order; import com.qniao.dam.domain.aggregate.order.entity.OrderItem; import com.qniao.dam.domain.aggregate.product.entity.Product; import com.qniao.dam.domain.aggregate.productspec.entity.ProductSpec; +import com.qniao.dam.domain.aggregate.revenuereward.entity.RevenueReward; +import com.qniao.dam.domain.aggregate.revenuereward.valueobj.RevenueRewardAssociateOrderRecord; +import com.qniao.dam.domain.aggregate.revenuereward.valueobj.RevenueRewardRecord; import com.qniao.dam.domain.aggregate.virtualaccount.VirtualAccountAggregate; import com.qniao.dam.domain.aggregate.virtualaccount.entity.VirtualAccount; +import com.qniao.dam.domain.aggregate.walletaccount.entity.WalletAccount; +import com.qniao.dam.domain.aggregate.walletaccount.valueobj.WalletAccountRecord; import com.qniao.dam.domain.service.virtualaccount.ConsumeVirtualAccountDomainService; import com.qniao.dam.domian.aggregate.order.constant.OrderBelongingEnum; import com.qniao.dam.domian.aggregate.order.constant.OrderStatusEnum; import com.qniao.dam.domian.aggregate.order.constant.OrderTypeEnum; +import com.qniao.dam.domian.aggregate.virtualaccount.constant.VirtualAccountTradeTypeEnum; +import com.qniao.dam.domian.aggregate.walletaccount.constant.IdentityTypeEnum; +import com.qniao.dam.domian.aggregate.walletaccount.constant.TradeSceneEnum; import com.qniao.dam.infrastructure.persistent.dao.domain.ProductDao; import com.qniao.dam.infrastructure.persistent.dao.domain.ProductSpecDao; import com.qniao.dam.infrastructure.utils.SnowFlakeUtil; +import com.qniao.dam.query.revenuereward.RevenueRewardQueryService; import com.qniao.dam.query.virtualaccount.VirtualAccountQueryService; +import com.qniao.dam.query.walletaccount.WalletAccountQueryService; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; +import java.util.Objects; @Service public class VirtualAccountApplicationService { @@ -30,6 +48,10 @@ public class VirtualAccountApplicationService { @Resource private VirtualAccountQueryService virtualAccountQueryService; @Resource + private WalletAccountQueryService walletAccountQueryService; + @Resource + private RevenueRewardQueryService revenueRewardQueryService; + @Resource private ProductDao productDao; @Resource private ProductSpecDao productSpecDao; @@ -58,7 +80,7 @@ public class VirtualAccountApplicationService { ProductSpec productSpec = productSpecDao.selectById(dto.getProductSpecId()); if (virtualAccount != null && virtualAccount.getBalance() >= productSpec.getUnitSellingPrice().intValue()) { //余额充足 创建消费订单+扣除余额 - Order order = handleOrder(dto.getUserId(), productSpec); + Order order = handleOrder(dto.getUserId(), productSpec, 1); //虚拟账户处理 virtualAccountAggregate.handleConsumeData(virtualAccount, order.getSettlementAmount().intValue(), dto.getTradeType()); //保存 @@ -70,16 +92,17 @@ public class VirtualAccountApplicationService { return vo; } - private Order handleOrder(Long userId, ProductSpec productSpec) { + private Order handleOrder(Long userId, ProductSpec productSpec, Integer quantity) { Product product = productDao.selectById(productSpec.getProductId()); + BigDecimal costAmount = productSpec.getUnitSellingPrice().multiply(new BigDecimal(quantity)); Order order = new Order(); order.setUserId(userId); order.setOrderBelonging(OrderBelongingEnum.CUSTOMER); order.setName(product.getProductTitle()); order.setOrderType(OrderTypeEnum.VIRTUAL_TYPE); order.setOrderCode(snowFlakeUtil.getSnowflakeOrderCode()); - order.setOriginalAmount(productSpec.getUnitSellingPrice()); - order.setSettlementAmount(productSpec.getUnitSellingPrice()); + order.setOriginalAmount(costAmount); + order.setSettlementAmount(costAmount); order.setPaidTime(LocalDateTime.now()); order.setStatus(OrderStatusEnum.COMPLETED); @@ -91,12 +114,77 @@ public class VirtualAccountApplicationService { orderItem.setSubCategory(product.getSubCategory()); orderItem.setProductTitle(product.getProductTitle()); orderItem.setProductDesc(product.getProductDesc()); - orderItem.setUnitOriginalPrice(productSpec.getUnitSellingPrice()); - orderItem.setUnitSettlementPrice(productSpec.getUnitSellingPrice()); - orderItem.setQuantity(1); - orderItem.setOriginalAmount(productSpec.getUnitSellingPrice()); - orderItem.setSettlementAmount(productSpec.getUnitSellingPrice()); + orderItem.setUnitOriginalPrice(costAmount); + orderItem.setUnitSettlementPrice(costAmount); + orderItem.setQuantity(quantity); + orderItem.setOriginalAmount(costAmount); + orderItem.setSettlementAmount(costAmount); order.setOrderItemList(Collections.singletonList(orderItem)); return order; } + + /** + * 1.判断虚拟账户余额 + * + * @param dto + * @return + */ + public CostIMGiftVo costIMGift(UserCostIMGiftDto dto) { + //判断虚拟账户余额 + CostIMGiftVo vo = new CostIMGiftVo(); + synchronized (dto.getFromUserId().toString().intern()) { + VirtualAccount virtualAccount = virtualAccountQueryService.queryBy(dto.getFromUserId()); + //找到对应产品 + ProductSpec productSpec = productSpecDao.selectById(dto.getProductSpecId()); + Integer costBalance = productSpec.getUnitSellingPrice().intValue() * dto.getQuantity(); + if (virtualAccount != null && virtualAccount.getBalance() >= costBalance) { + //余额充足 创建消费订单+扣除余额 + Order order = handleOrder(dto.getFromUserId(), productSpec, dto.getQuantity()); + //虚拟账户处理 + virtualAccountAggregate.handleConsumeData(virtualAccount, order.getSettlementAmount().intValue(), VirtualAccountTradeTypeEnum.GIFT); + //奖励处理 + Tuple tuple = handleIMGiftReward(dto.getToUserId(), costBalance); + //保存 + consumeVirtualAccountDomainService.handle(virtualAccount, order); + vo.setFlag(true); + } + } + return vo; + } + + private Tuple handleIMGiftReward(Long userId, Integer costBalance) { + //收益信息 + RevenueReward revenueReward = revenueRewardQueryService.queryByUserId(userId); + if (Objects.isNull(revenueReward)) { + revenueReward = RevenueReward.initUser(userId); + } + //营收额 + BigDecimal revenue = dto.getReceivedAmount(); + //服务费用 + serviceFee = serviceFeeRewardConfig.calculateReward(revenue); + BigDecimal earnings = revenue.subtract(serviceFee); + RevenueRewardRecord revenueRewardRecord = RevenueRewardRecord.build(tradeType, TradeSceneEnum.ONLINE, + revenue, BigDecimal.valueOf(100), new BigDecimal(serviceFeeRewardConfig.getValue()), earnings, dto.getTotalAssociateOrderAmount()); + revenueRewardRecord.handleContent(Collections.singletonList(meetingMi.getNickName())); + if (CollUtil.isNotEmpty(dto.getOrderIdRelList())) { + List associateOrderRecordList = new ArrayList<>(); + for (Long associateOrderId : dto.getOrderIdRelList()) { + Order associateOrder = orderDao.selectById(associateOrderId); + RevenueRewardAssociateOrderRecord associateOrderRecord = RevenueRewardAssociateOrderRecord.build(associateOrder.getId(), associateOrder.getSettlementAmount()); + revenueRewardRecord.setAssociateOrderRecordList(Collections.singletonList(associateOrderRecord)); + associateOrderRecordList.add(associateOrderRecord); + } + revenueRewardRecord.setAssociateOrderRecordList(associateOrderRecordList); + } + revenueReward.setRecordList(Collections.singletonList(revenueRewardRecord)); + //钱包 + WalletAccount walletAccount = walletAccountQueryService.queryByType(dto.getReceiver(), IdentityTypeEnum.INDIVIDUAL); + BigDecimal originalBalance = walletAccount.getTotalBalance(); + walletAccount.setAvailableBalance(walletAccount.getAvailableBalance().add(earnings)); + walletAccount.setTotalBalance(walletAccount.getAvailableBalance().add(walletAccount.getFrozenBalance())); + WalletAccountRecord walletAccountRecord = WalletAccountRecord.build(tradeType, earnings, true, originalBalance, walletAccount.getTotalBalance()); + walletAccount.setRecordList(Collections.singletonList(walletAccountRecord)); + acquireRevenueRewardDomainService.handle(revenueReward, walletAccount); + } + } \ No newline at end of file