From 5027bc943d7b5f954fe1bc9dca54a1b459db202e Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Tue, 18 Nov 2025 17:40:35 +0800 Subject: [PATCH] =?UTF-8?q?wallet=E7=94=A8=E6=88=B7=E5=B7=A5=E8=B5=84?= =?UTF-8?q?=E8=B4=A6=E6=88=B7=E6=95=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/UserSalaryAccountClientApi.java | 8 +- .../user/UserBankBalanceBackServiceImpl.java | 18 +- .../adapter/app/BankRestController.java | 7 +- .../app/SalaryAccountRestController.java | 57 +++-- .../command/bank/UserBankWithdrawCmdExe.java | 68 +++--- .../salary/SalaryExchangeGoldCmdExe.java | 223 ++++++++++++++++++ .../salary/SalaryTransferGoldCmdExe.java | 176 ++++++++++++++ ...e.java => SalaryWithdrawRefundCmdExe.java} | 8 +- .../query/SalaryAccountBalanceQryExe.java | 10 +- .../app/convertor/SalaryAccountConvertor.java | 65 +++-- .../app/service/SalaryAccountServiceImpl.java | 35 ++- .../clientobject/SalaryAccountBalanceCO.java | 5 + .../wallet/app/dto/cmd/SalaryWithdrawCmd.java | 17 +- .../app/service/SalaryAccountService.java | 30 ++- .../domain/gateway/SalaryAccountGateway.java | 7 +- .../wallet/domain/salary/SalaryEvent.java | 12 +- .../dao/salary/SalaryAccountBalanceDAO.java | 40 +++- .../entity/salary/SalaryAccountBalance.java | 2 + .../salary/SalaryAccountBalanceService.java | 58 ++++- .../impl/SalaryAccountBalanceServiceImpl.java | 43 ++-- .../gateway/SalaryAccountGatewayImpl.java | 39 +-- .../dao/salary/SalaryAccountBalanceDAO.xml | 4 + .../SalaryAccountInnerConvertor.java | 3 - .../UserSalaryAccountClientEndpoint.java | 8 +- .../UserSalaryAccountClientService.java | 4 +- .../UserSalaryAccountClientServiceImpl.java | 8 +- 26 files changed, 759 insertions(+), 196 deletions(-) create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryExchangeGoldCmdExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java rename rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/{SalaryWithdrawCmdExe.java => SalaryWithdrawRefundCmdExe.java} (72%) diff --git a/rc-service/rc-inner-api/wallet-inner/wallet-inner-api/src/main/java/com/red/circle/wallet/inner/endpoint/salary/api/UserSalaryAccountClientApi.java b/rc-service/rc-inner-api/wallet-inner/wallet-inner-api/src/main/java/com/red/circle/wallet/inner/endpoint/salary/api/UserSalaryAccountClientApi.java index e8313214..9ab30721 100644 --- a/rc-service/rc-inner-api/wallet-inner/wallet-inner-api/src/main/java/com/red/circle/wallet/inner/endpoint/salary/api/UserSalaryAccountClientApi.java +++ b/rc-service/rc-inner-api/wallet-inner/wallet-inner-api/src/main/java/com/red/circle/wallet/inner/endpoint/salary/api/UserSalaryAccountClientApi.java @@ -24,7 +24,7 @@ public interface UserSalaryAccountClientApi { * 查询余额. */ @GetMapping("/balance") - ResultResponse getBalance(@RequestParam("userId") Long userId); + ResultResponse getBalance(@RequestParam("userId") Long userId, @RequestParam("salaryType") String salaryType); /** * 发放工资. @@ -33,10 +33,10 @@ public interface UserSalaryAccountClientApi { ResultResponse issueSalary(@RequestBody SalaryIssueInnerCmd cmd); /** - * 提现. + * 提现回退 */ - @PostMapping("/withdraw") - ResultResponse withdrawSalary(@RequestBody SalaryWithdrawInnerCmd cmd); + @PostMapping("/withdraw-refund") + ResultResponse withdrawRefund(@RequestBody SalaryWithdrawInnerCmd cmd); /** * 查询流水. diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/user/UserBankBalanceBackServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/user/UserBankBalanceBackServiceImpl.java index 9112dc19..8e4a2b0a 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/user/UserBankBalanceBackServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/user/UserBankBalanceBackServiceImpl.java @@ -28,9 +28,7 @@ import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.ResponseErrorCode; import com.red.circle.other.inner.asserts.user.UserErrorCode; import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; -import com.red.circle.other.inner.endpoint.user.user.SysUserProfileClient; import com.red.circle.other.inner.endpoint.user.user.UserProfileClient; -import com.red.circle.other.inner.enums.team.TeamPolicyTypeEnum; import com.red.circle.other.inner.model.cmd.user.UserRegionConfigMapCmd; import com.red.circle.other.inner.model.dto.user.UserProfileDTO; import com.red.circle.other.inner.model.dto.user.reigon.RegionConfigDTO; @@ -47,6 +45,7 @@ import com.red.circle.wallet.inner.endpoint.bank.UserBankCardClient; import com.red.circle.wallet.inner.endpoint.bank.UserBankRunningWaterClient; import com.red.circle.wallet.inner.endpoint.diamond.SalaryDiamondBalanceClient; import com.red.circle.wallet.inner.endpoint.diamond.SalaryDiamondRunningWaterClient; +import com.red.circle.wallet.inner.endpoint.salary.UserSalaryAccountClient; import com.red.circle.wallet.inner.error.BankErrorCode; import com.red.circle.wallet.inner.error.WalletErrorCode; import com.red.circle.wallet.inner.model.cmd.*; @@ -94,6 +93,7 @@ public class UserBankBalanceBackServiceImpl implements UserBankBalanceBackServic private final IUserBaseInfoService userBaseInfoService; private final SysUserBankBalanceService userBankBalanceService; private final SysUserBankRunningWaterService userBankRunningWaterService; + private final UserSalaryAccountClient userSalaryAccountClient; @@ -818,13 +818,17 @@ public class UserBankBalanceBackServiceImpl implements UserBankBalanceBackServic ) ); - // 如果是驳回则将金额还给用户银行卡账户且插入返还日志 - if (Objects.isNull(apply.getAmountType())) { - saveUserBankBalance(param, apply); - } else if (Objects.equals(apply.getAmountType(), TeamPolicyTypeEnum.SALARY_DIAMOND.name())){ - saveUserBankDiamondBalance(param, apply); + if (WithdrawMoneyApprovalProcessStatus.NOT_PASS.equals(status)) { + } + // 如果是驳回则将金额还给用户银行卡账户且插入返还日志 +// if (Objects.isNull(apply.getAmountType())) { +// saveUserBankBalance(param, apply); +// } else if (Objects.equals(apply.getAmountType(), TeamPolicyTypeEnum.SALARY_DIAMOND.name())){ +// saveUserBankDiamondBalance(param, apply); +// } + } @Override diff --git a/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/BankRestController.java b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/BankRestController.java index f2914a91..60184963 100644 --- a/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/BankRestController.java +++ b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/BankRestController.java @@ -84,12 +84,7 @@ public class BankRestController extends BaseController { } /** - * 提现. - * - * @eo.name 提现. - * @eo.url /withdraw - * @eo.method post - * @eo.request-type json + * 用户工资提现(扣除用户工资账户) */ @PostMapping("/withdraw") public UserBankWithdrawResultCO withdraw(@RequestBody @Validated UserBankWithdrawCmd cmd) { diff --git a/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/SalaryAccountRestController.java b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/SalaryAccountRestController.java index 9a8eef3e..1a089991 100644 --- a/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/SalaryAccountRestController.java +++ b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/SalaryAccountRestController.java @@ -3,13 +3,10 @@ package com.red.circle.wallet.adapter.app; import com.red.circle.common.business.dto.cmd.AppExtCommand; import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.web.controller.BaseController; -import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO; -import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.clientobject.*; +import com.red.circle.wallet.app.dto.cmd.*; import com.red.circle.wallet.app.service.SalaryAccountService; +import com.red.circle.wallet.domain.salary.SalaryType; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -31,30 +28,60 @@ public class SalaryAccountRestController extends BaseController { /** * 查询余额. + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @return 余额信息 */ @GetMapping("/balance") - public SalaryAccountBalanceCO getBalance(AppExtCommand cmd) { - return salaryAccountService.getBalance(cmd.getReqUserId()); + public SalaryAccountBalanceCO getBalance(AppExtCommand cmd, String salaryType) { + return salaryAccountService.getBalance(cmd.getReqUserId(), salaryType); } /** * 发放工资. + * + * @param cmd 发放命令 + * @return 发放结果 */ @PostMapping("/issue") public SalaryIssueResultCO issueSalary(@RequestBody @Validated SalaryIssueCmd cmd) { return salaryAccountService.issueSalary(cmd); } - /** - * 提现. - */ - @PostMapping("/withdraw") - public void withdrawSalary(@RequestBody @Validated SalaryWithdrawCmd cmd) { - salaryAccountService.withdrawSalary(cmd); - } + /** + * 转账到金币. + * + * @eo.name 转账到金币. + * @eo.url /transferGold + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/transferGold") + public UserBankWithdrawResultCO transferGold( + @RequestBody @Validated SalaryWithdrawCmd cmd) { + return salaryAccountService.transferGold(cmd); + } + + /** + * 兑换金币. + * + * @eo.name 兑换金币. + * @eo.url /exchange/gold + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/exchange/gold") + public UserBankExchangeGoldResultCO exchangeGold( + @RequestBody @Validated SalaryWithdrawCmd cmd) { + return salaryAccountService.exchangeGold(cmd); + } /** * 查询流水. + * + * @param cmd 查询命令 + * @return 流水列表 */ @GetMapping("/running-water") public PageResult queryRunningWater(@Validated SalaryRunningWaterQueryCmd cmd) { diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankWithdrawCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankWithdrawCmdExe.java index 19d49a63..d3dee719 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankWithdrawCmdExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankWithdrawCmdExe.java @@ -19,20 +19,20 @@ import com.red.circle.tool.core.text.StringUtils; import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.wallet.app.dto.clientobject.UserBankWithdrawResultCO; import com.red.circle.wallet.app.dto.cmd.UserBankWithdrawCmd; +import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; +import com.red.circle.wallet.domain.salary.SalaryEvent; +import com.red.circle.wallet.domain.salary.SalaryReceipt; +import com.red.circle.wallet.domain.salary.SalaryReceiptRes; +import com.red.circle.wallet.domain.salary.SalaryType; import com.red.circle.wallet.infra.database.cache.service.WalletBankCacheService; import com.red.circle.wallet.infra.database.mongo.dto.UserBankWithdrawMoneyApprovalProcess; import com.red.circle.wallet.infra.database.mongo.dto.WithdrawMoneyApprovalProcessStatus; import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankCard; -import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankRunningWater; import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankWithdrawMoneyApply; -import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService; import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankCardService; -import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankRunningWaterService; import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankWithdrawMoneyApplyService; import com.red.circle.wallet.inner.error.BankErrorCode; import com.red.circle.wallet.inner.error.WalletErrorCode; -import com.red.circle.wallet.inner.model.dto.BankBalanceDTO; -import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent; import com.red.circle.wallet.inner.model.enums.WithdrawMethod; import java.math.BigDecimal; import java.math.RoundingMode; @@ -53,35 +53,43 @@ public class UserBankWithdrawCmdExe { private final RedisService redisService; private final RegionConfigClient regionConfigClient; private final UserBankCardService userBankCardService; - private final UserBankBalanceService userBankBalanceService; private final WalletBankCacheService walletBankCacheService; private final RegionAssistConfigClient regionAssistConfigClient; - private final UserBankRunningWaterService userBankRunningWaterService; private final UserBankWithdrawMoneyApplyService userBankWithdrawMoneyApplyService; + private final SalaryAccountGateway salaryAccountGateway; public UserBankWithdrawResultCO execute(UserBankWithdrawCmd cmd) { - ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, - ArithmeticUtils.gtZero(cmd.getAmount())); -// -// ResponseAssert.isFalse(CommonErrorCode.MSG_REPEAT_PROCESSING, -// walletBankCacheService.checkMonthWithdrawal(cmd.requiredReqUserId())); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, ArithmeticUtils.gtZero(cmd.getAmount())); // 上锁 String key = "UBWithdraw:" + cmd.requiredReqUserId(); ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60)); - BankBalanceDTO balance = userBankBalanceService.getBalance(cmd.requiredReqUserId()); + SalaryType salaryType = SalaryType.BD_SALARY; - ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, - ArithmeticUtils.gte(balance.getAccurateBalance(), cmd.getAmount())); + PennyAmount availableBalance = salaryAccountGateway.getAvailableBalance(cmd.getReqUserId(), salaryType); + BigDecimal balance = availableBalance.getDollarAmount(); + + // 3. 校验提现金额 + ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, ArithmeticUtils.gte(balance, cmd.getAmount())); UserBankCard bankCard = userBankCardService.getById(cmd.getAcceptBankCardId()); ResponseAssert.notNull(BankErrorCode.BANK_CARD_NOT_FOUND, bankCard); // 扣钱 - BankBalanceDTO decrUserBankBalanceDTO = userBankBalanceService.decr(cmd.requiredReqUserId(), - PennyAmount.ofDollar(cmd.getAmount())); - ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, decrUserBankBalanceDTO); + SalaryReceipt receipt = new SalaryReceipt() + .setReceiptType(ReceiptType.EXPENDITURE) + .setUserId(cmd.getReqUserId()) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setSalaryType(salaryType) + .setSalaryEvent(SalaryEvent.WITHDRAW) + .setAmount(PennyAmount.ofDollar(cmd.getAmount())) + .setTrackId(IdWorkerUtils.getIdStr()) + .setEventDesc("提现") + .setOpUserType(OpUserType.APP) + .setOpUserId(cmd.getReqUserId()); + SalaryReceiptRes salaryReceiptRes = salaryAccountGateway.changeBalance(receipt); + ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, salaryReceiptRes); Long bankRunWaterId = IdWorkerUtils.getId(); Long applyId = IdWorkerUtils.getId(); @@ -90,28 +98,6 @@ public class UserBankWithdrawCmdExe { Long serviceCharge = getAssistDiamondConfig(cmd.requiredReqUserId()); BigDecimal actualAmount = getActualAmount(cmd.getAmount(), serviceCharge); - // 银行卡流水 - userBankRunningWaterService.add( - new UserBankRunningWater() - .setId(bankRunWaterId) - .setUserId(cmd.requiredReqUserId()) - .setSysOrigin(cmd.requireReqSysOrigin()) - .setType(ReceiptType.EXPENDITURE.getType()) - .setAmount(cmd.getAmount()) - .setServiceCharge(serviceCharge) - .setActualAmount(actualAmount) - .setEvent(UserBankWaterEvent.WITHDRAW.name()) - .setEventDescribe(UserBankWaterEvent.WITHDRAW.getDescribe()) - .setRemark("Cash withdrawal") - .setTrackId(applyId.toString()) - .setBalance(decrUserBankBalanceDTO.getAccurateBalance()) - .setCreateTime(TimestampUtils.now()) - .setUpdateTime(TimestampUtils.now()) - .setCreateUser(cmd.requiredReqUserId()) - .setCreateUserOrigin(OpUserType.APP.getType()) - ); - - // 申请详情 userBankWithdrawMoneyApplyService.add( new UserBankWithdrawMoneyApply() @@ -142,7 +128,7 @@ public class UserBankWithdrawCmdExe { walletBankCacheService.setMonthWithdrawal(cmd.requiredReqUserId()); redisService.unlock(key); return new UserBankWithdrawResultCO() - .setBankBalance(decrUserBankBalanceDTO.getAccurateBalance()) + .setBankBalance(salaryReceiptRes.getAvailableBalance().getDollarAmount()) .setWithdrawAmount(Objects.toString(cmd.getAmount())); } diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryExchangeGoldCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryExchangeGoldCmdExe.java new file mode 100644 index 00000000..e30e13fb --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryExchangeGoldCmdExe.java @@ -0,0 +1,223 @@ +package com.red.circle.wallet.app.command.salary; + +import com.red.circle.common.business.core.enums.OpUserType; +import com.red.circle.common.business.core.enums.ReceiptType; +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.component.redis.service.RedisService; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.framework.core.response.CommonErrorCode; +import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.framework.dto.ResultResponse; +import com.red.circle.order.inner.endpoint.UserFreightRechargeRecordClient; +import com.red.circle.order.inner.endpoint.UserRechargeCountClient; +import com.red.circle.order.inner.model.enums.MonthlyRechargeType; +import com.red.circle.other.inner.endpoint.team.target.UserBillDiamondBalanceClient; +import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; +import com.red.circle.other.inner.endpoint.user.user.UserSvipClient; +import com.red.circle.other.inner.model.dto.agency.agency.BillDiamondBalanceDTO; +import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO; +import com.red.circle.tool.core.date.TimestampUtils; +import com.red.circle.tool.core.num.ArithmeticUtils; +import com.red.circle.tool.core.sequence.IdWorkerUtils; +import com.red.circle.tool.core.tuple.PennyAmount; +import com.red.circle.wallet.app.convertor.SalaryAccountConvertor; +import com.red.circle.wallet.app.dto.clientobject.UserBankExchangeGoldResultCO; +import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.cmd.UserBankExchangeGoldCmd; +import com.red.circle.wallet.app.dto.cmd.UserBillExchangeGoldCmd; +import com.red.circle.wallet.app.service.SalaryAccountService; +import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; +import com.red.circle.wallet.domain.gateway.WalletGoldGateway; +import com.red.circle.wallet.domain.salary.SalaryReceipt; +import com.red.circle.wallet.domain.salary.SalaryReceiptRes; +import com.red.circle.wallet.domain.salary.SalaryType; +import com.red.circle.wallet.domain.wallet.WalletReceipt; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankRunningWater; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankWithdrawGoldApply; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankRunningWaterService; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankWithdrawGoldApplyService; +import com.red.circle.wallet.infra.database.rds.entity.diamond.SalaryDiamondBalance; +import com.red.circle.wallet.infra.database.rds.entity.diamond.SalaryDiamondRunningWater; +import com.red.circle.wallet.infra.database.rds.entity.freight.FreightBalanceRunningWater; +import com.red.circle.wallet.infra.database.rds.service.diamond.SalaryDiamondBalanceService; +import com.red.circle.wallet.infra.database.rds.service.diamond.SalaryDiamondRunningWaterService; +import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceRunningWaterService; +import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceService; +import com.red.circle.wallet.inner.error.WalletErrorCode; +import com.red.circle.wallet.inner.model.dto.BankBalanceDTO; +import com.red.circle.wallet.inner.model.enums.FreightBalanceOrigin; +import com.red.circle.wallet.inner.model.enums.GoldOrigin; +import com.red.circle.wallet.inner.model.enums.GoldWithdrawAcceptAccount; +import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 用户工资余额兑换金币. + */ +@Component +@RequiredArgsConstructor +public class SalaryExchangeGoldCmdExe { + + private static final Logger log = LoggerFactory.getLogger(SalaryExchangeGoldCmdExe.class); + private final RedisService redisService; + private final UserRegionClient userRegionClient; + private final WalletGoldGateway walletGoldGateway; + private final FreightBalanceService freightBalanceService; + private final UserFreightRechargeRecordClient userFreightRechargeRecordClient; + private final UserBankWithdrawGoldApplyService userBankWithdrawGoldApplyService; + private final FreightBalanceRunningWaterService freightBalanceRunningWaterService; + private final UserRechargeCountClient userRechargeCountClient; + private final SalaryAccountGateway salaryAccountGateway; + private final SalaryAccountConvertor salaryAccountConvertor; + + public UserBankExchangeGoldResultCO execute(SalaryWithdrawCmd cmd) { + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + ArithmeticUtils.gtZero(cmd.getAmount())); + + String key = "USEGold:" + cmd.getReqUserId(); + ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60)); + + BigDecimal balance = salaryAccountGateway.getAvailableBalance(cmd.getReqUserId(), SalaryType.BD_SALARY).getDollarAmount(); + ResponseAssert.isFalse(WalletErrorCode.INSUFFICIENT_BALANCE, + !ArithmeticUtils.gte(balance, cmd.getAmount())); + + boolean freight = freightBalanceService.existsBalance(cmd.getReqUserId()); + + // 获得区域兑换比例金币比例 + Double goldRatio = getExchangeGoldRatio(cmd); + + // 扣钱 + SalaryReceipt receipt = salaryAccountConvertor.toExchangeReceipt(cmd); + SalaryReceiptRes salaryReceiptRes = salaryAccountGateway.changeBalance(receipt); + ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, salaryReceiptRes); + + BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN); + Long bankRunWaterId = IdWorkerUtils.getId(); + Long applyId = IdWorkerUtils.getId(); + + // 申请详情 + userBankWithdrawGoldApplyService.add( + new UserBankWithdrawGoldApply() + .setId(applyId) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setAcceptAccount((freight + ? GoldWithdrawAcceptAccount.FREIGHT + : GoldWithdrawAcceptAccount.GOLD).name()) + .setAcceptUserId(cmd.getReqUserId()) + .setSubmitUserId(cmd.getReqUserId()) + .setAmount(cmd.getAmount()) + .setGoldQuantity(goldQuantity.stripTrailingZeros().toPlainString()) + .setExchangeRate(Objects.toString(goldRatio)) + .setCreateTime(TimestampUtils.now()) + .setUpdateTime(TimestampUtils.now()) + .setCreateUser(cmd.getReqUserId()) + .setUpdateUser(cmd.getReqUserId()) + .setCreateUserOrigin(OpUserType.APP.getType()) + .setUpdateUserOrigin(OpUserType.APP.getType()) + ); + + sendGold(cmd, freight, goldQuantity, bankRunWaterId, "银行卡兑换"); + + // 记录充值金额 + rechargeRecord(cmd); + + userRechargeCountClient.count( cmd.getReqUserId(), + cmd.getAmount(), + MonthlyRechargeType.SHIPPING_AGENT + ); + + redisService.unlock(key); + return new UserBankExchangeGoldResultCO() + .setBankBalance(salaryReceiptRes.getAvailableBalance().getDollarAmount()) + .setExchangeGold(Objects.toString(goldRatio)); + } + + private void rechargeRecord(SalaryWithdrawCmd cmd) { + userFreightRechargeRecordClient.inrNowMonthAmount( + cmd.getReqUserId(), + cmd.getAmount() + ); + } + + /** + * 获得1$兑换多少金币比例, 基于区域+用户输入的美元. + * + * @return 1美元可获得的金币数量. + */ + private Double getExchangeGoldRatio(SalaryWithdrawCmd cmd) { + + boolean freight = freightBalanceService.existsBalance(cmd.getReqUserId()); + + List exchangeGolds = ResponseAssert.requiredSuccess( + userRegionClient + .listRegionExchangeGoldTip(cmd.getReqUserId(), freight) + ); + ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds); + + exchangeGolds = exchangeGolds.stream().filter(gold -> + cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getStart())) >= 0 && + cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getEnd())) <= 0) + .collect(Collectors.toList()); + ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds); + + SysExchangeGoldTipDTO exchangeGold = exchangeGolds.get(0); + ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, exchangeGold); + ResponseAssert.isFalse(CommonErrorCode.CONFIGURATION_ERROR, + Objects.isNull(exchangeGold.getValue()) || exchangeGold.getValue() <= 0); + + return exchangeGold.getValue(); + } + + private void sendGold(SalaryWithdrawCmd cmd, boolean freight, BigDecimal goldQuantity, + Long bankRunWaterId, String remark) { + if (freight) { + // 货运代理入账 + ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE, + freightBalanceService + .incrCandyBalance(SysOriginPlatformEnum.valueOf(cmd.getReqSysOrigin().getOrigin()), + cmd.getReqUserId(), goldQuantity)); + + // 插入流水 + BigDecimal freightBalance = freightBalanceService.getAvailableBalance( + cmd.getReqUserId()); + freightBalanceRunningWaterService.save(new FreightBalanceRunningWater() + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setUserId(cmd.getReqUserId()) + .setAcceptUserId(cmd.getReqUserId()) + .setType(ReceiptType.INCOME.getType()) + .setQuantity(goldQuantity) + .setUsdQuantity(cmd.getAmount()) + .setBalance(freightBalance) + .setOrigin(FreightBalanceOrigin.PURCHASE.name()) + .setRemark(remark) + .withCreateUser(cmd.getReqUserId())); + return; + } + + // 金币入账 + walletGoldGateway.changeBalance(new WalletReceipt() + .setReqTraceId(cmd.getReqTraceId()) + .setReceiptType(ReceiptType.INCOME) + .setUserId(cmd.getReqUserId()) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setEventType(Objects.toString(GoldOrigin.BANK_GOLD_COIN_EXCHANGE)) + .setEventDesc(GoldOrigin.BANK_GOLD_COIN_EXCHANGE.getDesc()) + .setEventId(Objects.toString(bankRunWaterId)) + .setAmount(PennyAmount.ofDollar(goldQuantity.longValue())) + .setOpUserType(OpUserType.APP) + .setCreateTime(cmd.getReqTime()) + ); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java new file mode 100644 index 00000000..69c89a53 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java @@ -0,0 +1,176 @@ +package com.red.circle.wallet.app.command.salary; + +import com.red.circle.common.business.core.enums.OpUserType; +import com.red.circle.common.business.core.enums.ReceiptType; +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.component.redis.service.RedisService; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.framework.core.response.CommonErrorCode; +import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; +import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO; +import com.red.circle.tool.core.date.TimestampUtils; +import com.red.circle.tool.core.num.ArithmeticUtils; +import com.red.circle.tool.core.sequence.IdWorkerUtils; +import com.red.circle.tool.core.tuple.PennyAmount; +import com.red.circle.wallet.app.convertor.SalaryAccountConvertor; +import com.red.circle.wallet.app.dto.clientobject.UserBankWithdrawResultCO; +import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.cmd.UserBankWithdrawTransferCmd; +import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; +import com.red.circle.wallet.domain.gateway.WalletGoldGateway; +import com.red.circle.wallet.domain.salary.SalaryReceipt; +import com.red.circle.wallet.domain.salary.SalaryReceiptRes; +import com.red.circle.wallet.domain.salary.SalaryType; +import com.red.circle.wallet.domain.wallet.WalletReceipt; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankRunningWater; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankBalanceService; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankRunningWaterService; +import com.red.circle.wallet.infra.database.rds.entity.freight.FreightBalanceRunningWater; +import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceRunningWaterService; +import com.red.circle.wallet.infra.database.rds.service.freight.FreightBalanceService; +import com.red.circle.wallet.inner.error.WalletErrorCode; +import com.red.circle.wallet.inner.model.dto.BankBalanceDTO; +import com.red.circle.wallet.inner.model.enums.FreightBalanceOrigin; +import com.red.circle.wallet.inner.model.enums.GoldOrigin; +import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 用户工资转账到金币命令执行器 + * + * @author system + */ +@Component +@RequiredArgsConstructor +public class SalaryTransferGoldCmdExe { + + private final RedisService redisService; + private final UserBankBalanceService userBankBalanceService; + private final UserBankRunningWaterService userBankRunningWaterService; + private final WalletGoldGateway walletGoldGateway; + private final FreightBalanceService freightBalanceService; + private final UserRegionClient userRegionClient; + private final FreightBalanceRunningWaterService freightBalanceRunningWaterService; + private final SalaryAccountGateway salaryAccountGateway; + private final SalaryAccountConvertor salaryAccountConvertor; + + /** + * 执行转账到金币操作 + * + * @param cmd 转账命令 + * @return 转账结果 + */ + public UserBankWithdrawResultCO execute(SalaryWithdrawCmd cmd) { + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + ArithmeticUtils.gtZero(cmd.getAmount())); + + boolean freight = freightBalanceService.existsBalance(cmd.getAcceptUserId()); + ResponseAssert.isTrue(WalletErrorCode.TARGET_USER_NOT_RECHARGE_AGENCY, freight); + ResponseAssert.isTrue(WalletErrorCode.NOT_TRANSFER_YOURSELF, !Objects.equals(cmd.getAcceptUserId(), cmd.requiredReqUserId())); + + // 上锁 + String key = "USTransferGold:" + cmd.requiredReqUserId(); + ResponseAssert.isTrue(CommonErrorCode.REQUEST_LIMITING, redisService.lock(key, 60)); + + BigDecimal balance = salaryAccountGateway.getAvailableBalance(cmd.getReqUserId(), SalaryType.BD_SALARY).getDollarAmount(); + + ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, + ArithmeticUtils.gte(balance, cmd.getAmount())); + + // 获得区域兑换比例金币比例 + Double goldRatio = getExchangeGoldRatio(cmd); + + // 扣钱 + SalaryReceipt receipt = salaryAccountConvertor.toTransferReceipt(cmd); + SalaryReceiptRes salaryReceiptRes = salaryAccountGateway.changeBalance(receipt); + ResponseAssert.notNull(WalletErrorCode.INSUFFICIENT_BALANCE, salaryReceiptRes); + + Long bankRunWaterId = IdWorkerUtils.getId(); + BigDecimal goldQuantity = BigDecimal.valueOf(goldRatio).multiply(cmd.getAmount()).setScale(0, RoundingMode.DOWN); + + // 发送金额 + sendGold(cmd, freight, goldQuantity, bankRunWaterId, "转账金币"); + + redisService.unlock(key); + return new UserBankWithdrawResultCO() + .setBankBalance(salaryReceiptRes.getAvailableBalance().getDollarAmount()) + .setWithdrawAmount(Objects.toString(cmd.getAmount())); + } + + private void sendGold(SalaryWithdrawCmd cmd, boolean freight, BigDecimal goldQuantity, + Long bankRunWaterId, String remark) { + if (freight) { + // 货运代理入账 + ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE, + freightBalanceService + .incrCandyBalance(SysOriginPlatformEnum.valueOf(cmd.getReqSysOrigin().getOrigin()), + cmd.getAcceptUserId(), goldQuantity)); + + // 插入流水 + BigDecimal freightBalance = freightBalanceService.getAvailableBalance(cmd.getAcceptUserId()); + freightBalanceRunningWaterService.save(new FreightBalanceRunningWater() + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setUserId(cmd.getReqUserId()) + .setAcceptUserId(cmd.getAcceptUserId()) + .setType(ReceiptType.INCOME.getType()) + .setQuantity(goldQuantity) + .setUsdQuantity(cmd.getAmount()) + .setBalance(freightBalance) + .setOrigin(FreightBalanceOrigin.PURCHASE.name()) + .setRemark(remark) + .withCreateUser(cmd.getReqUserId())); + return; + } + + // 金币入账 + walletGoldGateway.changeBalance(new WalletReceipt() + .setReqTraceId(cmd.getReqTraceId()) + .setReceiptType(ReceiptType.INCOME) + .setUserId(cmd.getAcceptUserId()) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setEventType(Objects.toString(GoldOrigin.BANK_GOLD_COIN_TRANSFER)) + .setEventDesc(GoldOrigin.BANK_GOLD_COIN_TRANSFER.getDesc()) + .setEventId(Objects.toString(bankRunWaterId)) + .setAmount(PennyAmount.ofDollar(goldQuantity.longValue())) + .setOpUserType(OpUserType.APP) + .setCreateTime(cmd.getReqTime()) + ); + } + + /** + * 获得1$兑换多少金币比例, 基于区域+用户输入的美元. + * + * @return 1美元可获得的金币数量. + */ + private Double getExchangeGoldRatio(SalaryWithdrawCmd cmd) { + Long acceptUserId = cmd.getAcceptUserId(); + + boolean freight = freightBalanceService.existsBalance(acceptUserId); + + List exchangeGolds = ResponseAssert.requiredSuccess( + userRegionClient.listRegionExchangeGoldTip(acceptUserId, freight)); + ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds); + + exchangeGolds = exchangeGolds.stream().filter(gold -> + cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getStart())) >= 0 && + cmd.getAmount().compareTo(BigDecimal.valueOf(gold.getEnd())) <= 0) + .collect(Collectors.toList()); + ResponseAssert.notEmpty(CommonErrorCode.CONFIGURATION_ERROR, exchangeGolds); + + SysExchangeGoldTipDTO exchangeGold = exchangeGolds.get(0); + ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, exchangeGold); + ResponseAssert.isFalse(CommonErrorCode.CONFIGURATION_ERROR, + Objects.isNull(exchangeGold.getValue()) || exchangeGold.getValue() <= 0); + + return exchangeGold.getValue(); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawRefundCmdExe.java similarity index 72% rename from rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawCmdExe.java rename to rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawRefundCmdExe.java index 445e4134..aa6ea1dd 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawCmdExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryWithdrawRefundCmdExe.java @@ -3,7 +3,6 @@ package com.red.circle.wallet.app.command.salary; import com.red.circle.wallet.app.convertor.SalaryAccountConvertor; import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; -import com.red.circle.wallet.domain.salary.SalaryReceipt; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -12,13 +11,14 @@ import org.springframework.stereotype.Component; */ @Component @RequiredArgsConstructor -public class SalaryWithdrawCmdExe { +public class SalaryWithdrawRefundCmdExe { private final SalaryAccountGateway salaryAccountGateway; private final SalaryAccountConvertor salaryAccountConvertor; public void execute(SalaryWithdrawCmd cmd) { - SalaryReceipt receipt = salaryAccountConvertor.toWithdrawReceipt(cmd); - salaryAccountGateway.changeBalance(receipt); + // 提现回退 + + } } diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/query/SalaryAccountBalanceQryExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/query/SalaryAccountBalanceQryExe.java index c2b7f4da..353e985c 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/query/SalaryAccountBalanceQryExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/query/SalaryAccountBalanceQryExe.java @@ -1,9 +1,8 @@ package com.red.circle.wallet.app.command.salary.query; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.red.circle.wallet.app.convertor.SalaryAccountConvertor; import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO; +import com.red.circle.wallet.domain.salary.SalaryType; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance; import com.red.circle.wallet.infra.database.rds.service.salary.SalaryAccountBalanceService; import java.math.BigDecimal; @@ -21,15 +20,14 @@ public class SalaryAccountBalanceQryExe { private final SalaryAccountBalanceService salaryAccountBalanceService; private final SalaryAccountConvertor salaryAccountConvertor; - public SalaryAccountBalanceCO execute(Long userId) { - LambdaQueryWrapper eq = Wrappers.lambdaQuery(SalaryAccountBalance.class) - .eq(SalaryAccountBalance::getUserId, userId); - SalaryAccountBalance balance = salaryAccountBalanceService.getOne(eq); + public SalaryAccountBalanceCO execute(Long userId, SalaryType salaryType) { + SalaryAccountBalance balance = salaryAccountBalanceService.getByUserIdAndType(userId, salaryType); if (Objects.isNull(balance)) { // 账户不存在,返回空余额 SalaryAccountBalanceCO co = new SalaryAccountBalanceCO(); co.setUserId(userId); + co.setSalaryType(salaryType.getCode()); co.setEarnPoints(BigDecimal.ZERO); co.setConsumptionPoints(BigDecimal.ZERO); co.setBalance(BigDecimal.ZERO); diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/SalaryAccountConvertor.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/SalaryAccountConvertor.java index bd798da0..26ad6cb8 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/SalaryAccountConvertor.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/SalaryAccountConvertor.java @@ -2,7 +2,7 @@ package com.red.circle.wallet.app.convertor; import com.red.circle.common.business.core.enums.OpUserType; import com.red.circle.common.business.core.enums.ReceiptType; -import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; +import com.red.circle.tool.core.sequence.IdWorkerUtils; import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO; import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO; @@ -16,9 +16,8 @@ import com.red.circle.wallet.domain.salary.SalaryType; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater; import java.math.BigDecimal; +import java.time.ZoneId; import java.util.Objects; - -import com.red.circle.wallet.infra.util.TimeConvertUtils; import org.springframework.stereotype.Component; /** @@ -49,29 +48,61 @@ public class SalaryAccountConvertor { public SalaryReceipt toWithdrawReceipt(SalaryWithdrawCmd cmd) { SalaryReceipt receipt = new SalaryReceipt() .setReceiptType(ReceiptType.EXPENDITURE) - .setUserId(cmd.getUserId()) + .setUserId(cmd.getReqUserId()) .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) - .setSalaryType(SalaryType.BD_SALARY) + .setSalaryType(SalaryType.of(cmd.getSalaryType())) .setSalaryEvent(SalaryEvent.WITHDRAW) .setAmount(PennyAmount.ofDollar(cmd.getAmount())) - .setTrackId(cmd.getTrackId()) + .setTrackId(IdWorkerUtils.getIdStr()) .setEventDesc("提现") .setRemark(cmd.getRemark()) .setOpUserType(OpUserType.APP) .setOpUserId(cmd.getReqUserId()); - if (Objects.nonNull(cmd.getServiceCharge()) && cmd.getServiceCharge() > 0) { - receipt.setServiceCharge(cmd.getServiceCharge()); - BigDecimal chargeRate = new BigDecimal(cmd.getServiceCharge()).divide(new BigDecimal("1000")); - BigDecimal actualAmount = cmd.getAmount().multiply(BigDecimal.ONE.subtract(chargeRate)); - receipt.setActualAmount(PennyAmount.ofDollar(actualAmount)); - } else { - receipt.setActualAmount(PennyAmount.ofDollar(cmd.getAmount())); - } +// if (Objects.nonNull(cmd.getServiceCharge()) && cmd.getServiceCharge() > 0) { +// receipt.setServiceCharge(cmd.getServiceCharge()); +// BigDecimal chargeRate = new BigDecimal(cmd.getServiceCharge()).divide(new BigDecimal("1000")); +// BigDecimal actualAmount = cmd.getAmount().multiply(BigDecimal.ONE.subtract(chargeRate)); +// receipt.setActualAmount(PennyAmount.ofDollar(actualAmount)); +// } else { +// receipt.setActualAmount(PennyAmount.ofDollar(cmd.getAmount())); +// } return receipt; } + public SalaryReceipt toExchangeReceipt(SalaryWithdrawCmd cmd) { + SalaryReceipt receipt = new SalaryReceipt() + .setReceiptType(ReceiptType.EXPENDITURE) + .setUserId(cmd.getReqUserId()) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setSalaryType(SalaryType.of(cmd.getSalaryType())) + .setSalaryEvent(SalaryEvent.SALARY_EXCHANGE) + .setAmount(PennyAmount.ofDollar(cmd.getAmount())) + .setTrackId(IdWorkerUtils.getIdStr()) + .setEventDesc(SalaryEvent.SALARY_EXCHANGE.getDesc()) + .setRemark(cmd.getRemark()) + .setOpUserType(OpUserType.APP) + .setOpUserId(cmd.getReqUserId()); + return receipt; + } + + public SalaryReceipt toTransferReceipt(SalaryWithdrawCmd cmd) { + SalaryReceipt receipt = new SalaryReceipt() + .setReceiptType(ReceiptType.EXPENDITURE) + .setUserId(cmd.getReqUserId()) + .setSysOrigin(cmd.getReqSysOrigin().getOrigin()) + .setSalaryType(SalaryType.of(cmd.getSalaryType())) + .setSalaryEvent(SalaryEvent.SALARY_TRANSFER) + .setAmount(PennyAmount.ofDollar(cmd.getAmount())) + .setTrackId(IdWorkerUtils.getIdStr()) + .setEventDesc(SalaryEvent.SALARY_TRANSFER.getDesc()) + .setRemark(cmd.getRemark()) + .setOpUserType(OpUserType.APP) + .setOpUserId(cmd.getReqUserId()); + return receipt; + } + public SalaryIssueResultCO toIssueResultCO(SalaryReceiptRes res) { SalaryIssueResultCO co = new SalaryIssueResultCO(); co.setRecordId(res.getRecordId()); @@ -87,6 +118,7 @@ public class SalaryAccountConvertor { } SalaryAccountBalanceCO co = new SalaryAccountBalanceCO(); co.setUserId(entity.getUserId()); + co.setSalaryType(entity.getSalaryType()); co.setEarnPoints(entity.getEarnPoints()); co.setConsumptionPoints(entity.getConsumptionPoints()); co.setBalance(entity.getBalance()); @@ -121,7 +153,10 @@ public class SalaryAccountConvertor { co.setBdId(entity.getBdId()); co.setAgentId(entity.getAgentId()); co.setRemark(entity.getRemark()); - co.setCreatedAt(TimeConvertUtils.toLocalDateTime(entity.getCreateTime())); + if (Objects.nonNull(entity.getCreateTime())) { + co.setCreatedAt(entity.getCreateTime().toInstant() + .atZone(ZoneId.systemDefault()).toLocalDateTime()); + } return co; } } diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/SalaryAccountServiceImpl.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/SalaryAccountServiceImpl.java index fc6612c7..d8b68057 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/SalaryAccountServiceImpl.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/SalaryAccountServiceImpl.java @@ -1,16 +1,15 @@ package com.red.circle.wallet.app.service; import com.red.circle.framework.dto.PageResult; +import com.red.circle.wallet.app.command.salary.SalaryExchangeGoldCmdExe; import com.red.circle.wallet.app.command.salary.SalaryIssueCmdExe; -import com.red.circle.wallet.app.command.salary.SalaryWithdrawCmdExe; +import com.red.circle.wallet.app.command.salary.SalaryTransferGoldCmdExe; +import com.red.circle.wallet.app.command.salary.SalaryWithdrawRefundCmdExe; import com.red.circle.wallet.app.command.salary.query.SalaryAccountBalanceQryExe; import com.red.circle.wallet.app.command.salary.query.SalaryRunningWaterQryExe; -import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO; -import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.clientobject.*; +import com.red.circle.wallet.app.dto.cmd.*; +import com.red.circle.wallet.domain.salary.SalaryType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -24,11 +23,13 @@ public class SalaryAccountServiceImpl implements SalaryAccountService { private final SalaryAccountBalanceQryExe salaryAccountBalanceQryExe; private final SalaryRunningWaterQryExe salaryRunningWaterQryExe; private final SalaryIssueCmdExe salaryIssueCmdExe; - private final SalaryWithdrawCmdExe salaryWithdrawCmdExe; + private final SalaryWithdrawRefundCmdExe salaryWithdrawRefundCmdExe; + private final SalaryExchangeGoldCmdExe salaryExchangeGoldCmdExe; + private final SalaryTransferGoldCmdExe salaryTransferGoldCmdExe; @Override - public SalaryAccountBalanceCO getBalance(Long userId) { - return salaryAccountBalanceQryExe.execute(userId); + public SalaryAccountBalanceCO getBalance(Long userId, String salaryType) { + return salaryAccountBalanceQryExe.execute(userId, SalaryType.of(salaryType)); } @Override @@ -37,12 +38,22 @@ public class SalaryAccountServiceImpl implements SalaryAccountService { } @Override - public void withdrawSalary(SalaryWithdrawCmd cmd) { - salaryWithdrawCmdExe.execute(cmd); + public void withdrawRefund(SalaryWithdrawCmd cmd) { + salaryWithdrawRefundCmdExe.execute(cmd); } @Override public PageResult queryRunningWater(SalaryRunningWaterQueryCmd cmd) { return salaryRunningWaterQryExe.execute(cmd); } + + @Override + public UserBankWithdrawResultCO transferGold(SalaryWithdrawCmd cmd) { + return salaryTransferGoldCmdExe.execute(cmd); + } + + @Override + public UserBankExchangeGoldResultCO exchangeGold(SalaryWithdrawCmd cmd) { + return salaryExchangeGoldCmdExe.execute(cmd); + } } diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/SalaryAccountBalanceCO.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/SalaryAccountBalanceCO.java index 7b4dae63..9370dec0 100644 --- a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/SalaryAccountBalanceCO.java +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/SalaryAccountBalanceCO.java @@ -15,6 +15,11 @@ public class SalaryAccountBalanceCO { */ private Long userId; + /** + * 工资类型. + */ + private String salaryType; + /** * 累计收入. */ diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/SalaryWithdrawCmd.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/SalaryWithdrawCmd.java index c519b4fc..a744641c 100644 --- a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/SalaryWithdrawCmd.java +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/SalaryWithdrawCmd.java @@ -16,10 +16,10 @@ import lombok.EqualsAndHashCode; public class SalaryWithdrawCmd extends AppExtCommand { /** - * 用户ID. + * 工资类型. */ - @NotNull(message = "userId required.") - private Long userId; + @NotBlank(message = "salaryType required.") + private String salaryType; /** * 提现金额. @@ -28,16 +28,15 @@ public class SalaryWithdrawCmd extends AppExtCommand { @DecimalMin(value = "0.01", message = "amount must > 0") private BigDecimal amount; - /** - * 业务单号. - */ - @NotBlank(message = "trackId required.") - private String trackId; + /** + * 接收用户(Transfer 使用) + */ + private Long acceptUserId; /** * 手续费比例(千分比). */ - private Long serviceCharge; +// private Long serviceCharge; /** * 备注. diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/SalaryAccountService.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/SalaryAccountService.java index ea485db2..644a3b53 100644 --- a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/SalaryAccountService.java +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/SalaryAccountService.java @@ -1,12 +1,8 @@ package com.red.circle.wallet.app.service; import com.red.circle.framework.dto.PageResult; -import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO; -import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO; -import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd; -import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.clientobject.*; +import com.red.circle.wallet.app.dto.cmd.*; /** * 工资账户服务. @@ -15,21 +11,37 @@ public interface SalaryAccountService { /** * 查询余额. + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @return 余额信息 */ - SalaryAccountBalanceCO getBalance(Long userId); + SalaryAccountBalanceCO getBalance(Long userId, String salaryType); /** * 发放工资. + * + * @param cmd 发放命令 + * @return 发放结果 */ SalaryIssueResultCO issueSalary(SalaryIssueCmd cmd); /** - * 提现. + * 提现回退 + * + * @param cmd 提现命令 */ - void withdrawSalary(SalaryWithdrawCmd cmd); + void withdrawRefund(SalaryWithdrawCmd cmd); /** * 查询流水. + * + * @param cmd 查询命令 + * @return 流水列表 */ PageResult queryRunningWater(SalaryRunningWaterQueryCmd cmd); + + UserBankWithdrawResultCO transferGold(SalaryWithdrawCmd cmd); + + UserBankExchangeGoldResultCO exchangeGold(SalaryWithdrawCmd cmd); } diff --git a/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/gateway/SalaryAccountGateway.java b/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/gateway/SalaryAccountGateway.java index e5296ee2..ee0ea097 100644 --- a/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/gateway/SalaryAccountGateway.java +++ b/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/gateway/SalaryAccountGateway.java @@ -3,6 +3,7 @@ package com.red.circle.wallet.domain.gateway; import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.wallet.domain.salary.SalaryReceipt; import com.red.circle.wallet.domain.salary.SalaryReceiptRes; +import com.red.circle.wallet.domain.salary.SalaryType; /** * 工资账户 Gateway. @@ -13,17 +14,19 @@ public interface SalaryAccountGateway { * 查询余额. * * @param userId 用户ID + * @param salaryType 工资类型 * @return 余额 */ - PennyAmount getBalance(Long userId); + PennyAmount getBalance(Long userId, SalaryType salaryType); /** * 查询可用余额. * * @param userId 用户ID + * @param salaryType 工资类型 * @return 可用余额 */ - PennyAmount getAvailableBalance(Long userId); + PennyAmount getAvailableBalance(Long userId, SalaryType salaryType); /** * 变更余额. diff --git a/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/salary/SalaryEvent.java b/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/salary/SalaryEvent.java index a0142dd4..3388708b 100644 --- a/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/salary/SalaryEvent.java +++ b/rc-service/rc-service-wallet/wallet-domain/src/main/java/com/red/circle/wallet/domain/salary/SalaryEvent.java @@ -25,7 +25,17 @@ public enum SalaryEvent { */ WITHDRAW("WITHDRAW", "提现"), - /** + /** + * 兑换 + */ + SALARY_EXCHANGE("SALARY_EXCHANGE", "工资兑换"), + + /** + * 兑换 + */ + SALARY_TRANSFER("SALARY_TRANSFER", "工资转账"), + + /** * 提现退回. */ WITHDRAW_REFUND("WITHDRAW_REFUND", "提现退回"), diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/dao/salary/SalaryAccountBalanceDAO.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/dao/salary/SalaryAccountBalanceDAO.java index dfa642e7..41c0238b 100644 --- a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/dao/salary/SalaryAccountBalanceDAO.java +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/dao/salary/SalaryAccountBalanceDAO.java @@ -1,35 +1,57 @@ package com.red.circle.wallet.infra.database.rds.dao.salary; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.red.circle.framework.mybatis.dao.BaseDAO; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance; -import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** - * 工资账户余额 Mapper. + * 工资账户余额 DAO. */ public interface SalaryAccountBalanceDAO extends BaseDAO { /** * 增加收入(累计). + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @param amount 金额(分) + * @return 影响行数 */ - int incrIncome(@Param("userId") Long userId, @Param("amount") Long amount); + int incrIncome(@Param("userId") Long userId, @Param("salaryType") String salaryType, + @Param("amount") Long amount); /** * 增加支出(累计). + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @param amount 金额(分) + * @return 影响行数 */ - int incrExpenditure(@Param("userId") Long userId, @Param("amount") Long amount); + int incrExpenditure(@Param("userId") Long userId, @Param("salaryType") String salaryType, + @Param("amount") Long amount); /** * 冻结金额. + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @param amount 金额(分) + * @param version 版本号 + * @return 影响行数 */ - int freezeAmount(@Param("userId") Long userId, @Param("amount") Long amount, - @Param("version") Integer version); + int freezeAmount(@Param("userId") Long userId, @Param("salaryType") String salaryType, + @Param("amount") Long amount, @Param("version") Integer version); /** * 解冻金额. + * + * @param userId 用户ID + * @param salaryType 工资类型 + * @param amount 金额(分) + * @param version 版本号 + * @return 影响行数 */ - int unfreezeAmount(@Param("userId") Long userId, @Param("amount") Long amount, - @Param("version") Integer version); + int unfreezeAmount(@Param("userId") Long userId, @Param("salaryType") String salaryType, + @Param("amount") Long amount, @Param("version") Integer version); } diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/entity/salary/SalaryAccountBalance.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/entity/salary/SalaryAccountBalance.java index 36073368..ac0bdea4 100644 --- a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/entity/salary/SalaryAccountBalance.java +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/entity/salary/SalaryAccountBalance.java @@ -35,6 +35,8 @@ public class SalaryAccountBalance { @TableField("user_id") private Long userId; + private String salaryType; + /** * 系统来源. */ diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/service/salary/SalaryAccountBalanceService.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/service/salary/SalaryAccountBalanceService.java index 48f9f57c..e8aab173 100644 --- a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/service/salary/SalaryAccountBalanceService.java +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/rds/service/salary/SalaryAccountBalanceService.java @@ -1,6 +1,7 @@ package com.red.circle.wallet.infra.database.rds.service.salary; import com.red.circle.framework.mybatis.service.BaseService; +import com.red.circle.wallet.domain.salary.SalaryType; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance; /** @@ -10,36 +11,79 @@ public interface SalaryAccountBalanceService extends BaseService implements SalaryAccountBalanceService { - private final SalaryAccountBalanceDAO salaryAccountBalanceDAO; + private final SalaryAccountBalanceDAO salaryAccountBalanceDAO; @Override - public void init(String sysOrigin, Long userId) { + public void init(String sysOrigin, Long userId, SalaryType salaryType) { SalaryAccountBalance balance = new SalaryAccountBalance() .setId(IdWorkerUtils.getId()) .setUserId(userId) + .setSalaryType(salaryType.getCode()) .setSysOrigin(sysOrigin) .setEarnPoints(BigDecimal.ZERO) .setConsumptionPoints(BigDecimal.ZERO) @@ -40,10 +41,8 @@ public class SalaryAccountBalanceServiceImpl } @Override - public Long getBalance(Long userId) { - LambdaQueryWrapper eq = Wrappers.lambdaQuery(SalaryAccountBalance.class) - .eq(SalaryAccountBalance::getUserId, userId); - SalaryAccountBalance balance = getOne(eq); + public Long getBalance(Long userId, SalaryType salaryType) { + SalaryAccountBalance balance = getByUserIdAndType(userId, salaryType); if (Objects.isNull(balance)) { return 0L; } @@ -51,10 +50,8 @@ public class SalaryAccountBalanceServiceImpl } @Override - public Long getAvailableBalance(Long userId) { - LambdaQueryWrapper eq = Wrappers.lambdaQuery(SalaryAccountBalance.class) - .eq(SalaryAccountBalance::getUserId, userId); - SalaryAccountBalance balance = getOne(eq); + public Long getAvailableBalance(Long userId, SalaryType salaryType) { + SalaryAccountBalance balance = getByUserIdAndType(userId, salaryType); if (Objects.isNull(balance)) { return 0L; } @@ -62,22 +59,30 @@ public class SalaryAccountBalanceServiceImpl } @Override - public boolean incrIncome(Long userId, Long amount) { - return salaryAccountBalanceDAO.incrIncome(userId, amount) > 0; + public boolean incrIncome(Long userId, SalaryType salaryType, Long amount) { + return salaryAccountBalanceDAO.incrIncome(userId, salaryType.getCode(), amount) > 0; } @Override - public boolean incrExpenditure(Long userId, Long amount) { - return salaryAccountBalanceDAO.incrExpenditure(userId, amount) > 0; + public boolean incrExpenditure(Long userId, SalaryType salaryType, Long amount) { + return salaryAccountBalanceDAO.incrExpenditure(userId, salaryType.getCode(), amount) > 0; } @Override - public boolean freezeAmount(Long userId, Long amount, Integer version) { - return salaryAccountBalanceDAO.freezeAmount(userId, amount, version) > 0; + public boolean freezeAmount(Long userId, SalaryType salaryType, Long amount, Integer version) { + return salaryAccountBalanceDAO.freezeAmount(userId, salaryType.getCode(), amount, version) > 0; } @Override - public boolean unfreezeAmount(Long userId, Long amount, Integer version) { - return salaryAccountBalanceDAO.unfreezeAmount(userId, amount, version) > 0; + public boolean unfreezeAmount(Long userId, SalaryType salaryType, Long amount, Integer version) { + return salaryAccountBalanceDAO.unfreezeAmount(userId, salaryType.getCode(), amount, version) > 0; + } + + @Override + public SalaryAccountBalance getByUserIdAndType(Long userId, SalaryType salaryType) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(SalaryAccountBalance.class) + .eq(SalaryAccountBalance::getUserId, userId) + .eq(SalaryAccountBalance::getSalaryType, salaryType.getCode()); + return getOne(wrapper); } } diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/gateway/SalaryAccountGatewayImpl.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/gateway/SalaryAccountGatewayImpl.java index 1df631fc..58266c92 100644 --- a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/gateway/SalaryAccountGatewayImpl.java +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/gateway/SalaryAccountGatewayImpl.java @@ -11,6 +11,7 @@ import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; import com.red.circle.wallet.domain.salary.SalaryReceipt; import com.red.circle.wallet.domain.salary.SalaryReceiptRes; +import com.red.circle.wallet.domain.salary.SalaryType; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountBalance; import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater; import com.red.circle.wallet.infra.database.rds.service.salary.SalaryAccountBalanceService; @@ -37,13 +38,13 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway { private final SalaryAccountRunningWaterService salaryAccountRunningWaterService; @Override - public PennyAmount getBalance(Long userId) { - return PennyAmount.ofPenny(salaryAccountBalanceService.getBalance(userId)); + public PennyAmount getBalance(Long userId, SalaryType salaryType) { + return PennyAmount.ofPenny(salaryAccountBalanceService.getBalance(userId, salaryType)); } @Override - public PennyAmount getAvailableBalance(Long userId) { - return PennyAmount.ofPenny(salaryAccountBalanceService.getAvailableBalance(userId)); + public PennyAmount getAvailableBalance(Long userId, SalaryType salaryType) { + return PennyAmount.ofPenny(salaryAccountBalanceService.getAvailableBalance(userId, salaryType)); } @Override @@ -54,14 +55,14 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway { } // 检查账户是否存在,不存在则初始化 - LambdaQueryWrapper eq = Wrappers.lambdaQuery() - .eq(SalaryAccountBalance::getUserId, receipt.getUserId()); - SalaryAccountBalance balance = salaryAccountBalanceService.getOne(eq); - + SalaryAccountBalance balance = salaryAccountBalanceService.getByUserIdAndType( + receipt.getUserId(), receipt.getSalaryType()); + if (Objects.isNull(balance)) { - salaryAccountBalanceService.init(receipt.getSysOrigin(), receipt.getUserId()); - balance = salaryAccountBalanceService.getOne(new LambdaQueryWrapper<>(SalaryAccountBalance.class) - .eq(SalaryAccountBalance::getUserId, receipt.getUserId())); + salaryAccountBalanceService.init(receipt.getSysOrigin(), receipt.getUserId(), + receipt.getSalaryType()); + balance = salaryAccountBalanceService.getByUserIdAndType( + receipt.getUserId(), receipt.getSalaryType()); } // 更新余额 @@ -69,11 +70,13 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway { if (receipt.getReceiptType() == ReceiptType.INCOME) { updateSuccess = salaryAccountBalanceService.incrIncome( receipt.getUserId(), + receipt.getSalaryType(), receipt.getAmount().getPennyAmount() ); } else { updateSuccess = salaryAccountBalanceService.incrExpenditure( - receipt.getUserId(), + receipt.getUserId(), + receipt.getSalaryType(), receipt.getAmount().getPennyAmount() ); } @@ -81,8 +84,10 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway { ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE, updateSuccess); // 查询更新后的余额 - Long newBalance = salaryAccountBalanceService.getBalance(receipt.getUserId()); - Long newAvailableBalance = salaryAccountBalanceService.getAvailableBalance(receipt.getUserId()); + Long newBalance = salaryAccountBalanceService.getBalance(receipt.getUserId(), + receipt.getSalaryType()); + Long newAvailableBalance = salaryAccountBalanceService.getAvailableBalance(receipt.getUserId(), + receipt.getSalaryType()); // 插入流水记录 Long recordId = IdWorkerUtils.getId(); @@ -92,9 +97,9 @@ public class SalaryAccountGatewayImpl implements SalaryAccountGateway { salaryAccountRunningWaterService.save(runningWater); } catch (DuplicateKeyException e) { // 幂等性:trackId重复,查询已有记录 - SalaryAccountRunningWater existingWater = salaryAccountRunningWaterService.getOne( - new LambdaQueryWrapper<>(SalaryAccountRunningWater.class) - .eq(SalaryAccountRunningWater::getTrackId, receipt.getTrackId())); + LambdaQueryWrapper eq = Wrappers.lambdaQuery(SalaryAccountRunningWater.class) + .eq(SalaryAccountRunningWater::getTrackId, receipt.getTrackId()); + SalaryAccountRunningWater existingWater = salaryAccountRunningWaterService.getOne(eq); if (Objects.nonNull(existingWater)) { return SalaryReceiptRes.of( existingWater.getId(), diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/resources/dao/salary/SalaryAccountBalanceDAO.xml b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/resources/dao/salary/SalaryAccountBalanceDAO.xml index 1dfb352e..d33c5ebc 100644 --- a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/resources/dao/salary/SalaryAccountBalanceDAO.xml +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/resources/dao/salary/SalaryAccountBalanceDAO.xml @@ -8,6 +8,7 @@ balance = balance + #{amount} / 100, available_balance = available_balance + #{amount} / 100 WHERE user_id = #{userId} + AND salary_type = #{salaryType} @@ -16,6 +17,7 @@ balance = balance - #{amount} / 100, available_balance = available_balance - #{amount} / 100 WHERE user_id = #{userId} + AND salary_type = #{salaryType} AND available_balance >= #{amount} / 100 @@ -25,6 +27,7 @@ available_balance = available_balance - #{amount} / 100, version = version + 1 WHERE user_id = #{userId} + AND salary_type = #{salaryType} AND version = #{version} AND available_balance >= #{amount} / 100 @@ -35,6 +38,7 @@ available_balance = available_balance + #{amount} / 100, version = version + 1 WHERE user_id = #{userId} + AND salary_type = #{salaryType} AND version = #{version} AND frozen_amount >= #{amount} / 100 diff --git a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/SalaryAccountInnerConvertor.java b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/SalaryAccountInnerConvertor.java index 7895b5f9..054b6300 100644 --- a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/SalaryAccountInnerConvertor.java +++ b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/SalaryAccountInnerConvertor.java @@ -50,10 +50,7 @@ public class SalaryAccountInnerConvertor { return null; } SalaryWithdrawCmd cmd = new SalaryWithdrawCmd(); - cmd.setUserId(innerCmd.getUserId()); cmd.setAmount(innerCmd.getAmount()); - cmd.setTrackId(innerCmd.getTrackId()); - cmd.setServiceCharge(innerCmd.getServiceCharge()); cmd.setRemark(innerCmd.getRemark()); // 设置请求来源信息 diff --git a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/endpoint/salary/UserSalaryAccountClientEndpoint.java b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/endpoint/salary/UserSalaryAccountClientEndpoint.java index df490b5c..0f53a03b 100644 --- a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/endpoint/salary/UserSalaryAccountClientEndpoint.java +++ b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/endpoint/salary/UserSalaryAccountClientEndpoint.java @@ -28,8 +28,8 @@ public class UserSalaryAccountClientEndpoint implements UserSalaryAccountClientA private final UserSalaryAccountClientService userSalaryAccountClientService; @Override - public ResultResponse getBalance(Long userId) { - return ResultResponse.success(userSalaryAccountClientService.getBalance(userId)); + public ResultResponse getBalance(Long userId, String salaryType) { + return ResultResponse.success(userSalaryAccountClientService.getBalance(userId, salaryType)); } @Override @@ -38,8 +38,8 @@ public class UserSalaryAccountClientEndpoint implements UserSalaryAccountClientA } @Override - public ResultResponse withdrawSalary(SalaryWithdrawInnerCmd cmd) { - userSalaryAccountClientService.withdrawSalary(cmd); + public ResultResponse withdrawRefund(SalaryWithdrawInnerCmd cmd) { + userSalaryAccountClientService.withdrawRefund(cmd); return ResultResponse.success(); } diff --git a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/UserSalaryAccountClientService.java b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/UserSalaryAccountClientService.java index f4f5c868..76980eba 100644 --- a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/UserSalaryAccountClientService.java +++ b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/UserSalaryAccountClientService.java @@ -16,7 +16,7 @@ public interface UserSalaryAccountClientService { /** * 查询余额. */ - SalaryAccountBalanceDTO getBalance(Long userId); + SalaryAccountBalanceDTO getBalance(Long userId, String salaryType); /** * 发放工资. @@ -26,7 +26,7 @@ public interface UserSalaryAccountClientService { /** * 提现. */ - void withdrawSalary(SalaryWithdrawInnerCmd cmd); + void withdrawRefund(SalaryWithdrawInnerCmd cmd); /** * 查询流水. diff --git a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/impl/UserSalaryAccountClientServiceImpl.java b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/impl/UserSalaryAccountClientServiceImpl.java index adf1b6c8..11a809a0 100644 --- a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/impl/UserSalaryAccountClientServiceImpl.java +++ b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/service/salary/impl/UserSalaryAccountClientServiceImpl.java @@ -33,8 +33,8 @@ public class UserSalaryAccountClientServiceImpl implements UserSalaryAccountClie private final SalaryAccountInnerConvertor salaryAccountInnerConvertor; @Override - public SalaryAccountBalanceDTO getBalance(Long userId) { - SalaryAccountBalanceCO co = salaryAccountService.getBalance(userId); + public SalaryAccountBalanceDTO getBalance(Long userId, String salaryType) { + SalaryAccountBalanceCO co = salaryAccountService.getBalance(userId, salaryType); return salaryAccountInnerConvertor.toBalanceDTO(co); } @@ -46,9 +46,9 @@ public class UserSalaryAccountClientServiceImpl implements UserSalaryAccountClie } @Override - public void withdrawSalary(SalaryWithdrawInnerCmd innerCmd) { + public void withdrawRefund(SalaryWithdrawInnerCmd innerCmd) { SalaryWithdrawCmd cmd = salaryAccountInnerConvertor.toWithdrawCmd(innerCmd); - salaryAccountService.withdrawSalary(cmd); + salaryAccountService.withdrawRefund(cmd); } @Override