From f6c82f83a9e21280a2fc34e8d44d3a3796fb978a Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Mon, 10 Nov 2025 00:06:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E6=8F=90=E7=8E=B0?= =?UTF-8?q?=E4=BF=A1=E6=81=AFCRUD=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wallet/inner/error/BankErrorCode.java | 10 + .../app/convertor/bank/BankAppConvertor.java | 6 + .../app/UserWithdrawInfoRestController.java | 102 +++++++++ .../command/bank/UserWithdrawInfoAddExe.java | 53 +++++ .../bank/UserWithdrawInfoDeleteExe.java | 24 +++ .../bank/UserWithdrawInfoUpdateExe.java | 64 ++++++ .../command/bank/UserWithdrawInfoUseExe.java | 24 +++ .../bank/query/UserWithdrawInfoQryExe.java | 31 +++ .../app/convertor/UserBankAppConvertor.java | 4 + .../UserWithdrawInfoApiServiceImpl.java | 57 +++++ .../dto/clientobject/UserWithdrawInfoCO.java | 83 ++++++++ .../app/dto/cmd/UserWithdrawInfoAddCmd.java | 54 +++++ .../dto/cmd/UserWithdrawInfoUpdateCmd.java | 63 ++++++ .../service/UserWithdrawInfoApiService.java | 42 ++++ .../mongo/entity/bank/UserWithdrawInfo.java | 106 +++++++++ .../service/bank/UserWithdrawInfoService.java | 111 ++++++++++ .../impl/UserWithdrawInfoServiceImpl.java | 201 ++++++++++++++++++ .../convertor/UserBankInnerConvertor.java | 12 ++ 18 files changed, 1047 insertions(+) create mode 100644 rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/UserWithdrawInfoRestController.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoAddExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoDeleteExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUpdateExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUseExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/query/UserWithdrawInfoQryExe.java create mode 100644 rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiServiceImpl.java create mode 100644 rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/UserWithdrawInfoCO.java create mode 100644 rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoAddCmd.java create mode 100644 rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoUpdateCmd.java create mode 100644 rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiService.java create mode 100644 rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/entity/bank/UserWithdrawInfo.java create mode 100644 rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/UserWithdrawInfoService.java create mode 100644 rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/impl/UserWithdrawInfoServiceImpl.java diff --git a/rc-service/rc-inner-api/wallet-inner/wallet-inner-model/src/main/java/com/red/circle/wallet/inner/error/BankErrorCode.java b/rc-service/rc-inner-api/wallet-inner/wallet-inner-model/src/main/java/com/red/circle/wallet/inner/error/BankErrorCode.java index bc87c009..b82d3532 100644 --- a/rc-service/rc-inner-api/wallet-inner/wallet-inner-model/src/main/java/com/red/circle/wallet/inner/error/BankErrorCode.java +++ b/rc-service/rc-inner-api/wallet-inner/wallet-inner-model/src/main/java/com/red/circle/wallet/inner/error/BankErrorCode.java @@ -31,6 +31,16 @@ public enum BankErrorCode implements IResponseErrorCode { * 无效银行卡 */ INVALID_BANK_CARD_ERROR(5303, "Invalid bank card"), + + /** + * 提现信息不存在. + */ + WITHDRAW_INFO_NOT_FOUND(5304, "Withdraw info not found"), + + /** + * 已存在相同类别的提现信息. + */ + REPEAT_WITHDRAW_INFO_ERROR(5305, "Withdraw info with the same category already exists"), ; diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/convertor/bank/BankAppConvertor.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/convertor/bank/BankAppConvertor.java index 495fa4ac..3d71fcf4 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/convertor/bank/BankAppConvertor.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/convertor/bank/BankAppConvertor.java @@ -2,11 +2,13 @@ package com.red.circle.console.app.convertor.bank; import com.red.circle.console.app.dto.clienobject.user.UserBankCardCO; import com.red.circle.console.app.dto.clienobject.user.UserBankIdentityInfoCO; +import com.red.circle.console.app.dto.clienobject.user.UserWithdrawInfoCO; import com.red.circle.framework.core.convertor.ConvertorModel; import com.red.circle.other.inner.model.dto.user.UserBankIdentityInfoDTO; import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyExportQryCmd; import com.red.circle.wallet.inner.model.cmd.UserBankWithdrawMoneyApplyQryCmd; import com.red.circle.wallet.inner.model.dto.UserBankCardDTO; +import com.red.circle.wallet.inner.model.dto.UserWithdrawInfoDTO; import java.util.List; import org.mapstruct.Mapper; @@ -24,4 +26,8 @@ public interface BankAppConvertor { UserBankCardCO toUserBankCardCO(UserBankCardDTO dto); UserBankIdentityInfoCO toUserBankIdentityInfoCO(UserBankIdentityInfoDTO dto); + + List toListUserWithdrawInfoCO(List dtos); + + UserWithdrawInfoCO toUserWithdrawInfoCO(UserWithdrawInfoDTO dto); } diff --git a/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/UserWithdrawInfoRestController.java b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/UserWithdrawInfoRestController.java new file mode 100644 index 00000000..65577f5c --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-adapter/src/main/java/com/red/circle/wallet/adapter/app/UserWithdrawInfoRestController.java @@ -0,0 +1,102 @@ +package com.red.circle.wallet.adapter.app; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.common.business.dto.cmd.IdLongCmd; +import com.red.circle.framework.web.controller.BaseController; +import com.red.circle.wallet.app.dto.clientobject.UserWithdrawInfoCO; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoAddCmd; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoUpdateCmd; +import com.red.circle.wallet.app.service.UserWithdrawInfoApiService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 用户提现信息服务. + * + * @author tf + * @eo.api-type http + * @eo.groupName 钱包服务.提现信息 + * @eo.path /wallet/withdraw-info + */ +@Slf4j +@RequiredArgsConstructor +@RestController +@RequestMapping(value = "/withdraw-info", produces = MediaType.APPLICATION_JSON_VALUE) +public class UserWithdrawInfoRestController extends BaseController { + + private final UserWithdrawInfoApiService userWithdrawInfoApiService; + + /** + * 根据用户id获得提现信息列表. + * + * @eo.name 根据用户id获得提现信息列表. + * @eo.url /list + * @eo.method get + * @eo.request-type formdata + */ + @GetMapping("/list") + public List listWithdrawInfo(AppExtCommand cmd) { + return userWithdrawInfoApiService.listWithdrawInfo(cmd); + } + + /** + * 根据id删除提现信息. + * + * @eo.name 根据id删除提现信息. + * @eo.url /delete + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/delete") + public void deleteById(@RequestBody @Validated IdLongCmd cmd) { + userWithdrawInfoApiService.deleteById(cmd); + } + + /** + * 使用提现信息. + * + * @eo.name 使用提现信息. + * @eo.url /use + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/use") + public void use(@RequestBody @Validated IdLongCmd cmd) { + userWithdrawInfoApiService.use(cmd); + } + + /** + * 添加用户提现信息. + * + * @eo.name 添加用户提现信息. + * @eo.url /add + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/add") + public void add(@RequestBody @Validated UserWithdrawInfoAddCmd cmd) { + userWithdrawInfoApiService.add(cmd); + } + + /** + * 修改用户提现信息. + * + * @eo.name 修改用户提现信息. + * @eo.url /update + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/update") + public void update(@RequestBody @Validated UserWithdrawInfoUpdateCmd cmd) { + userWithdrawInfoApiService.update(cmd); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoAddExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoAddExe.java new file mode 100644 index 00000000..5f5ae0e2 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoAddExe.java @@ -0,0 +1,53 @@ +package com.red.circle.wallet.app.command.bank; + +import com.red.circle.common.business.core.enums.ApprovalStatusEnum; +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.tool.core.date.TimestampUtils; +import com.red.circle.tool.core.sequence.IdWorkerUtils; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoAddCmd; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserWithdrawInfo; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import com.red.circle.wallet.inner.error.BankErrorCode; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 用户提现信息添加. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class UserWithdrawInfoAddExe { + + private final RedisService redisService; + private final UserWithdrawInfoService userWithdrawInfoService; + + public void execute(UserWithdrawInfoAddCmd cmd) { + + ResponseAssert.isTrue(CommonErrorCode.REPEATED_SUBMISSION, redisService.setIfAbsent( + "USER_WITHDRAW_INFO_ADD:" + cmd.requiredReqUserId(), 3, TimeUnit.SECONDS)); + + ResponseAssert.isFalse(BankErrorCode.REPEAT_WITHDRAW_INFO_ERROR, + userWithdrawInfoService.exist(cmd.requiredReqUserId(), cmd.getCategory())); + + userWithdrawInfoService.add(new UserWithdrawInfo() + .setId(IdWorkerUtils.getId()) + .setUserId(cmd.requiredReqUserId()) + .setSysOrigin(cmd.requireReqSysOrigin()) + .setStatus(ApprovalStatusEnum.PENDING.name()) + .setContactNumber(cmd.getContactNumber()) + .setCategory(cmd.getCategory()) + .setOtherDescription(cmd.getOtherDescription()) + .setPassportFrontUrl(cmd.getPassportFrontUrl()) + .setPassportBackUrl(cmd.getPassportBackUrl()) + .setDel(Boolean.FALSE) + .setCreateUser(cmd.requiredReqUserId()) + .setCreateTime(TimestampUtils.now()) + ); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoDeleteExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoDeleteExe.java new file mode 100644 index 00000000..44cb0f9b --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoDeleteExe.java @@ -0,0 +1,24 @@ +package com.red.circle.wallet.app.command.bank; + +import com.red.circle.common.business.dto.cmd.IdLongCmd; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 用户提现信息删除. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class UserWithdrawInfoDeleteExe { + + private final UserWithdrawInfoService userWithdrawInfoService; + + public void execute(IdLongCmd cmd) { + userWithdrawInfoService.deleteByIdByUserId(cmd.getId(), cmd.getReqUserId(), + cmd.requiredReqUserId()); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUpdateExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUpdateExe.java new file mode 100644 index 00000000..d8d6538c --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUpdateExe.java @@ -0,0 +1,64 @@ +package com.red.circle.wallet.app.command.bank; + +import com.red.circle.common.business.core.enums.ApprovalStatusEnum; +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.tool.core.date.TimestampUtils; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoUpdateCmd; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserWithdrawInfo; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import com.red.circle.wallet.inner.error.BankErrorCode; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 用户提现信息修改. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class UserWithdrawInfoUpdateExe { + + private final RedisService redisService; + private final UserWithdrawInfoService userWithdrawInfoService; + + public void execute(UserWithdrawInfoUpdateCmd cmd) { + + ResponseAssert.isTrue(CommonErrorCode.REPEATED_SUBMISSION, redisService.setIfAbsent( + "USER_WITHDRAW_INFO_UPDATE:" + cmd.requiredReqUserId(), 3, TimeUnit.SECONDS)); + + // 查询要修改的提现信息 + UserWithdrawInfo existInfo = userWithdrawInfoService.getById(cmd.getId()); + ResponseAssert.notNull(BankErrorCode.WITHDRAW_INFO_NOT_FOUND, existInfo); + + // 校验是否属于当前用户 + ResponseAssert.isTrue(BankErrorCode.WITHDRAW_INFO_NOT_FOUND, + Objects.equals(existInfo.getUserId(), cmd.requiredReqUserId())); + + // 如果修改了类别,需要检查新类别是否已存在 + if (!Objects.equals(existInfo.getCategory(), cmd.getCategory())) { + UserWithdrawInfo checkInfo = userWithdrawInfoService.getOne( + cmd.requiredReqUserId(), cmd.getCategory()); + // 如果找到了其他记录且不是当前记录,则报错 + ResponseAssert.isTrue(BankErrorCode.REPEAT_WITHDRAW_INFO_ERROR, + Objects.isNull(checkInfo) || Objects.equals(checkInfo.getId(), cmd.getId())); + } + + // 更新信息,重新提交审核 + existInfo.setContactNumber(cmd.getContactNumber()) + .setCategory(cmd.getCategory()) + .setOtherDescription(cmd.getOtherDescription()) + .setPassportFrontUrl(cmd.getPassportFrontUrl()) + .setPassportBackUrl(cmd.getPassportBackUrl()) + .setStatus(ApprovalStatusEnum.PENDING.name()) + .setUpdateUser(cmd.requiredReqUserId()) + .setUpdateTime(TimestampUtils.now()); + + userWithdrawInfoService.update(existInfo); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUseExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUseExe.java new file mode 100644 index 00000000..ef6babd9 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserWithdrawInfoUseExe.java @@ -0,0 +1,24 @@ +package com.red.circle.wallet.app.command.bank; + +import com.red.circle.common.business.dto.cmd.IdLongCmd; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 使用提现信息. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class UserWithdrawInfoUseExe { + + private final UserWithdrawInfoService userWithdrawInfoService; + + public void execute(IdLongCmd cmd) { + userWithdrawInfoService.use(cmd.getId(), cmd.requiredReqUserId(), + cmd.requiredReqUserId()); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/query/UserWithdrawInfoQryExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/query/UserWithdrawInfoQryExe.java new file mode 100644 index 00000000..af1fef0f --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/query/UserWithdrawInfoQryExe.java @@ -0,0 +1,31 @@ +package com.red.circle.wallet.app.command.bank.query; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.tool.core.collection.CollectionUtils; +import com.red.circle.wallet.app.convertor.UserBankAppConvertor; +import com.red.circle.wallet.app.dto.clientobject.UserWithdrawInfoCO; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * 用户提现信息查询. + * + * @author tf + */ +@Component +@RequiredArgsConstructor +public class UserWithdrawInfoQryExe { + + private final UserWithdrawInfoService userWithdrawInfoService; + private final UserBankAppConvertor userBankAppConvertor; + + public List execute(AppExtCommand cmd) { + return Optional.ofNullable(userBankAppConvertor.toListUserWithdrawInfo( + userWithdrawInfoService.listByUserId(cmd.requiredReqUserId()))) + .orElseGet(CollectionUtils::newArrayList); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/UserBankAppConvertor.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/UserBankAppConvertor.java index 068b19e3..df4b4e8c 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/UserBankAppConvertor.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/convertor/UserBankAppConvertor.java @@ -3,9 +3,11 @@ package com.red.circle.wallet.app.convertor; import com.red.circle.framework.core.convertor.ConvertorModel; import com.red.circle.wallet.app.dto.clientobject.UserBankCardCO; import com.red.circle.wallet.app.dto.clientobject.UserBankWithdrawMoneyApplyCO; +import com.red.circle.wallet.app.dto.clientobject.UserWithdrawInfoCO; 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.entity.bank.UserWithdrawInfo; import com.red.circle.wallet.inner.model.dto.UserBankCardDTO; import com.red.circle.wallet.inner.model.dto.UserBankRunningWaterDTO; import com.red.circle.wallet.inner.model.dto.UserBankWithdrawMoneyApplyDTO; @@ -31,4 +33,6 @@ public interface UserBankAppConvertor { UserBankCardDTO toUserBankCardDTO(UserBankCard userBankCard); + List toListUserWithdrawInfo(List userWithdrawInfos); + } diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiServiceImpl.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiServiceImpl.java new file mode 100644 index 00000000..9817708a --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiServiceImpl.java @@ -0,0 +1,57 @@ +package com.red.circle.wallet.app.service; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.common.business.dto.cmd.IdLongCmd; +import com.red.circle.wallet.app.command.bank.UserWithdrawInfoAddExe; +import com.red.circle.wallet.app.command.bank.UserWithdrawInfoDeleteExe; +import com.red.circle.wallet.app.command.bank.UserWithdrawInfoUpdateExe; +import com.red.circle.wallet.app.command.bank.UserWithdrawInfoUseExe; +import com.red.circle.wallet.app.command.bank.query.UserWithdrawInfoQryExe; +import com.red.circle.wallet.app.dto.clientobject.UserWithdrawInfoCO; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoAddCmd; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoUpdateCmd; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 用户提现信息服务. + * + * @author tf + */ +@Service +@RequiredArgsConstructor +public class UserWithdrawInfoApiServiceImpl implements UserWithdrawInfoApiService { + + private final UserWithdrawInfoAddExe userWithdrawInfoAddExe; + private final UserWithdrawInfoUpdateExe userWithdrawInfoUpdateExe; + private final UserWithdrawInfoUseExe userWithdrawInfoUseExe; + private final UserWithdrawInfoQryExe userWithdrawInfoQryExe; + private final UserWithdrawInfoDeleteExe userWithdrawInfoDeleteExe; + + @Override + public List listWithdrawInfo(AppExtCommand cmd) { + return userWithdrawInfoQryExe.execute(cmd); + } + + @Override + public void deleteById(IdLongCmd cmd) { + userWithdrawInfoDeleteExe.execute(cmd); + } + + @Override + public void add(UserWithdrawInfoAddCmd cmd) { + userWithdrawInfoAddExe.execute(cmd); + } + + @Override + public void use(IdLongCmd cmd) { + userWithdrawInfoUseExe.execute(cmd); + } + + @Override + public void update(UserWithdrawInfoUpdateCmd cmd) { + userWithdrawInfoUpdateExe.execute(cmd); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/UserWithdrawInfoCO.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/UserWithdrawInfoCO.java new file mode 100644 index 00000000..fee9cf8d --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/clientobject/UserWithdrawInfoCO.java @@ -0,0 +1,83 @@ +package com.red.circle.wallet.app.dto.clientobject; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.red.circle.framework.dto.ClientObject; +import java.sql.Timestamp; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 用户提现信息. + * + * @author tf + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class UserWithdrawInfoCO extends ClientObject { + + /** + * 记录id. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 用户id. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long userId; + + /** + * 归属系统. + */ + private String sysOrigin; + + /** + * true正在使用. + */ + private Boolean use; + + /** + * 审核状态: 等待审核,已通过,不通过. + */ + private String status; + + /** + * 联系电话. + */ + private String contactNumber; + + /** + * 类别. + */ + private String category; + + /** + * 其他描述. + */ + private String otherDescription; + + /** + * 护照/身份证正面照片URL. + */ + private String passportFrontUrl; + + /** + * 护照/身份证背面照片URL. + */ + private String passportBackUrl; + + /** + * 创建时间. + */ + private Timestamp createTime; + + /** + * 修改时间. + */ + private Timestamp updateTime; + +} diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoAddCmd.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoAddCmd.java new file mode 100644 index 00000000..ad2ac9d2 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoAddCmd.java @@ -0,0 +1,54 @@ +package com.red.circle.wallet.app.dto.cmd; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 添加用户提现信息. + * + * @author tf + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class UserWithdrawInfoAddCmd extends AppExtCommand { + + /** + * 联系电话. + * + * @eo.required + */ + @NotBlank(message = "contactNumber required.") + private String contactNumber; + + /** + * 类别. + * + * @eo.required + */ + @NotBlank(message = "category required.") + private String category; + + /** + * 其他描述. + */ + private String otherDescription; + + /** + * 护照/身份证正面照片URL. + * + * @eo.required + */ + @NotBlank(message = "passportFrontUrl required.") + private String passportFrontUrl; + + /** + * 护照/身份证背面照片URL. + * + * @eo.required + */ + @NotBlank(message = "passportBackUrl required.") + private String passportBackUrl; + +} diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoUpdateCmd.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoUpdateCmd.java new file mode 100644 index 00000000..f0282286 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/dto/cmd/UserWithdrawInfoUpdateCmd.java @@ -0,0 +1,63 @@ +package com.red.circle.wallet.app.dto.cmd; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 修改用户提现信息. + * + * @author tf + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class UserWithdrawInfoUpdateCmd extends AppExtCommand { + + /** + * 提现信息ID. + * + * @eo.required + */ + @NotNull(message = "id required.") + private Long id; + + /** + * 联系电话. + * + * @eo.required + */ + @NotBlank(message = "contactNumber required.") + private String contactNumber; + + /** + * 类别. + * + * @eo.required + */ + @NotBlank(message = "category required.") + private String category; + + /** + * 其他描述. + */ + private String otherDescription; + + /** + * 护照/身份证正面照片URL. + * + * @eo.required + */ + @NotBlank(message = "passportFrontUrl required.") + private String passportFrontUrl; + + /** + * 护照/身份证背面照片URL. + * + * @eo.required + */ + @NotBlank(message = "passportBackUrl required.") + private String passportBackUrl; + +} diff --git a/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiService.java b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiService.java new file mode 100644 index 00000000..edc8fa50 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-client/src/main/java/com/red/circle/wallet/app/service/UserWithdrawInfoApiService.java @@ -0,0 +1,42 @@ +package com.red.circle.wallet.app.service; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.common.business.dto.cmd.IdLongCmd; +import com.red.circle.wallet.app.dto.clientobject.UserWithdrawInfoCO; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoAddCmd; +import com.red.circle.wallet.app.dto.cmd.UserWithdrawInfoUpdateCmd; +import java.util.List; + +/** + * 用户提现信息服务. + * + * @author tf + */ +public interface UserWithdrawInfoApiService { + + /** + * 获得提现信息列表. + */ + List listWithdrawInfo(AppExtCommand cmd); + + /** + * 根据id删除提现信息. + */ + void deleteById(IdLongCmd cmd); + + /** + * 添加用户提现信息. + */ + void add(UserWithdrawInfoAddCmd cmd); + + /** + * 使用提现信息. + */ + void use(IdLongCmd cmd); + + /** + * 修改用户提现信息. + */ + void update(UserWithdrawInfoUpdateCmd cmd); + +} diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/entity/bank/UserWithdrawInfo.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/entity/bank/UserWithdrawInfo.java new file mode 100644 index 00000000..cb231ca4 --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/entity/bank/UserWithdrawInfo.java @@ -0,0 +1,106 @@ +package com.red.circle.wallet.infra.database.mongo.entity.bank; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import java.io.Serial; +import java.io.Serializable; +import java.sql.Timestamp; +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +/** + * 用户提现信息. + * + * @author tf + */ +@Data +@Accessors(chain = true) +@Document("user_withdraw_info") +public class UserWithdrawInfo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 记录id. + */ + @Id + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 用户id. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long userId; + + /** + * 归属系统. + */ + private String sysOrigin; + + /** + * true正在使用. + */ + private Boolean use; + + /** + * 审核状态: 等待审核,已通过,不通过. + */ + private String status; + + /** + * 联系电话. + */ + private String contactNumber; + + /** + * 类别. + */ + private String category; + + /** + * 其他描述. + */ + private String otherDescription; + + /** + * 护照/身份证正面照片URL. + */ + private String passportFrontUrl; + + /** + * 护照/身份证背面照片URL. + */ + private String passportBackUrl; + + /** + * 是否已删除(true是). + */ + private Boolean del; + + /** + * 创建时间. + */ + private Timestamp createTime; + + /** + * 修改时间. + */ + private Timestamp updateTime; + + /** + * 创建用户. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long createUser; + + /** + * 修改用户. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long updateUser; + +} diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/UserWithdrawInfoService.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/UserWithdrawInfoService.java new file mode 100644 index 00000000..4607063e --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/UserWithdrawInfoService.java @@ -0,0 +1,111 @@ +package com.red.circle.wallet.infra.database.mongo.service.bank; + +import com.red.circle.framework.dto.PageResult; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserWithdrawInfo; +import com.red.circle.wallet.inner.model.cmd.UserWithdrawInfoBackQryCmd; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 用户提现信息. + * + * @author tf + */ +public interface UserWithdrawInfoService { + + /** + * 检查提现信息是否存在. + * + * @param userId 用户id + * @param category 类别 + * @return true存在, false 不存在. + */ + Boolean exist(Long userId, String category); + + /** + * 根据id查询对象. + */ + UserWithdrawInfo getById(Long id); + + /** + * 获取用户正在使用的提现信息. + */ + UserWithdrawInfo getUseByUserId(Long userId); + + /** + * 添加. + */ + void add(UserWithdrawInfo info); + + /** + * 修改. + */ + void update(UserWithdrawInfo info); + + /** + * 根据用户id获得提现信息列表. + * + * @param userId 用户id + */ + List listByUserId(Long userId); + + /** + * 根据用户id获得提现信息列表-通过审核的. + * + * @param userId 用户id + */ + List listPassByUserId(Long userId); + + /** + * 删除提现信息. + * + * @param id id. + */ + void deleteByIdByUserId(Long id, Long userId, Long currentUidLong); + + /** + * 将提现信息设置为使用状态. + * + * @param id id. + */ + void use(Long id, Long userId, Long currentUidLong); + + /** + * 根据条件查询提现信息. + * + * @param userId 用户ID. + * @param category 类别. + */ + UserWithdrawInfo getOne(Long userId, String category); + + /** + * 移除用户相关提现信息. + */ + void removeBatchByUserId(List userIds); + + /** + * 通过审核. + * + * @param ids ids. + */ + void pass(Set ids, Long currentUidLong); + + /** + * 驳回. + * + * @param ids ids. + */ + void notPass(Set ids, Long currentUidLong); + + /** + * 提现信息列表分页. + */ + PageResult pageQuery(UserWithdrawInfoBackQryCmd query); + + /** + * 获取一组指定的提现信息. + */ + Map mapByIds(Set ids); + +} diff --git a/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/impl/UserWithdrawInfoServiceImpl.java b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/impl/UserWithdrawInfoServiceImpl.java new file mode 100644 index 00000000..0cbeb69a --- /dev/null +++ b/rc-service/rc-service-wallet/wallet-infrastructure/src/main/java/com/red/circle/wallet/infra/database/mongo/service/bank/impl/UserWithdrawInfoServiceImpl.java @@ -0,0 +1,201 @@ +package com.red.circle.wallet.infra.database.mongo.service.bank.impl; + +import com.google.common.collect.Maps; +import com.red.circle.common.business.core.enums.ApprovalStatusEnum; +import com.red.circle.component.mongodb.page.MongoPageHelper; +import com.red.circle.framework.dto.PageResult; +import com.red.circle.tool.core.collection.CollectionUtils; +import com.red.circle.tool.core.date.TimestampUtils; +import com.red.circle.tool.core.text.StringUtils; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserWithdrawInfo; +import com.red.circle.wallet.infra.database.mongo.service.bank.UserWithdrawInfoService; +import com.red.circle.wallet.inner.model.cmd.UserWithdrawInfoBackQryCmd; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Service; + +/** + * 用户提现信息. + * + * @author tf + */ +@Service +@RequiredArgsConstructor +public class UserWithdrawInfoServiceImpl implements UserWithdrawInfoService { + + private final MongoTemplate mongoTemplate; + private final MongoPageHelper mongoPageHelper; + + @Override + public Boolean exist(Long userId, String category) { + return mongoTemplate.exists(Query.query(Criteria.where("userId").is(userId) + .and("category").is(category).and("del").is(Boolean.FALSE)), UserWithdrawInfo.class); + } + + @Override + public UserWithdrawInfo getById(Long id) { + Query query = new Query(); + query.addCriteria(Criteria.where("id").is(id)); + return mongoTemplate.findOne(query, UserWithdrawInfo.class); + } + + @Override + public UserWithdrawInfo getUseByUserId(Long userId) { + return mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId) + .and("use").is(Boolean.TRUE).and("del").is(Boolean.FALSE)), UserWithdrawInfo.class); + } + + @Override + public void add(UserWithdrawInfo info) { + info.setUse(Boolean.FALSE); + mongoTemplate.save(info); + } + + @Override + public void update(UserWithdrawInfo info) { + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(info.getId())), + new Update() + .set("status", info.getStatus()) + .set("contactNumber", info.getContactNumber()) + .set("category", info.getCategory()) + .set("otherDescription", info.getOtherDescription()) + .set("passportFrontUrl", info.getPassportFrontUrl()) + .set("passportBackUrl", info.getPassportBackUrl()) + .set("updateTime", info.getUpdateTime()) + .set("updateUser", info.getUpdateUser()), + UserWithdrawInfo.class); + } + + @Override + public List listByUserId(Long userId) { + Query query = new Query(); + query.addCriteria(Criteria.where("userId").is(userId).and("del").is(Boolean.FALSE)); + query.with(Sort.by(Sort.Order.desc("createTime"), Sort.Order.desc("updateTime"))); + return mongoTemplate.find(query, UserWithdrawInfo.class); + } + + @Override + public List listPassByUserId(Long userId) { + Query query = Query.query(Criteria.where("userId").is(userId) + .and("status").is(ApprovalStatusEnum.PASS) + .and("del").is(Boolean.FALSE)) + .with(Sort.by(Sort.Order.desc("createTime"), Sort.Order.desc("updateTime"))); + return mongoTemplate.find(query, UserWithdrawInfo.class); + } + + @Override + public void deleteByIdByUserId(Long id, Long userId, Long currentUidLong) { + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id).and("userId").is(userId)), + new Update() + .set("del", Boolean.TRUE) + .set("updateUser", currentUidLong) + .set("updateTime", TimestampUtils.now()), + UserWithdrawInfo.class); + } + + @Override + public void use(Long id, Long userId, Long currentUidLong) { + Query query = new Query(); + query.addCriteria( + Criteria.where("id").is(id).and("userId").is(userId).and("del").is(Boolean.FALSE)); + UserWithdrawInfo userWithdrawInfo = mongoTemplate.findOne(query, UserWithdrawInfo.class); + if (Objects.isNull(userWithdrawInfo)) { + return; + } + // 将该用户所有提现信息设置为未使用 + mongoTemplate.updateMulti(Query.query(Criteria.where("userId").is(userWithdrawInfo.getUserId())), + new Update() + .set("use", Boolean.FALSE) + .set("updateUser", currentUidLong) + .set("updateTime", TimestampUtils.now()), + UserWithdrawInfo.class); + + // 将当前提现信息设置为使用 + mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)), + new Update() + .set("updateUser", currentUidLong) + .set("updateTime", TimestampUtils.now()) + .set("use", Boolean.TRUE), + UserWithdrawInfo.class); + } + + @Override + public UserWithdrawInfo getOne(Long userId, String category) { + Query query = new Query(); + query.addCriteria(Criteria.where("userId").is(userId) + .and("category").is(category)); + return mongoTemplate.findOne(query, UserWithdrawInfo.class); + } + + @Override + public void removeBatchByUserId(List userIds) { + mongoTemplate.remove(Query.query(Criteria.where("userId").in(userIds)), UserWithdrawInfo.class); + } + + @Override + public void pass(Set ids, Long currentUidLong) { + mongoTemplate.updateMulti(Query.query(Criteria.where("id").in(ids)), + new Update() + .set("updateUser", currentUidLong) + .set("updateTime", TimestampUtils.now()) + .set("status", ApprovalStatusEnum.PASS.name()), + UserWithdrawInfo.class); + } + + @Override + public void notPass(Set ids, Long currentUidLong) { + mongoTemplate.updateMulti(Query.query(Criteria.where("id").in(ids)), + new Update() + .set("use", Boolean.FALSE) + .set("updateUser", currentUidLong) + .set("updateTime", TimestampUtils.now()) + .set("status", ApprovalStatusEnum.NOT_PASS.name()), + UserWithdrawInfo.class); + } + + @Override + public PageResult pageQuery(UserWithdrawInfoBackQryCmd query) { + Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin()) + .and("status").is(query.getStatus()).and("del").is(Boolean.FALSE); + + if (Objects.nonNull(query.getUserId())) { + criteria.and("userId").is(query.getUserId()); + } + + if (StringUtils.isNotBlank(query.getCategory())) { + criteria.and("category").is(query.getCategory()); + } + + return mongoPageHelper.query(new Query(criteria), + UserWithdrawInfo.class, + query.getPageQuery().getLimit(), + query.getPageQuery().getCursor(), + Sort.Order.desc("createTime")); + } + + @Override + public Map mapByIds(Set ids) { + if (CollectionUtils.isEmpty(ids)) { + return Maps.newHashMap(); + } + + List infos = mongoTemplate.find(Query.query(Criteria.where("id").in(ids)), + UserWithdrawInfo.class); + + if (CollectionUtils.isEmpty(infos)) { + return Maps.newHashMap(); + } + + return infos.stream().collect(Collectors.toMap(UserWithdrawInfo::getId, v -> v)); + } + +} diff --git a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/UserBankInnerConvertor.java b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/UserBankInnerConvertor.java index a8aec211..278c14f7 100644 --- a/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/UserBankInnerConvertor.java +++ b/rc-service/rc-service-wallet/wallet-inner-endpoint/src/main/java/com/red/circle/wallet/inner/convertor/UserBankInnerConvertor.java @@ -6,12 +6,15 @@ 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.UserBankWithdrawGoldApply; import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankWithdrawMoneyApply; +import com.red.circle.wallet.infra.database.mongo.entity.bank.UserWithdrawInfo; import com.red.circle.wallet.inner.model.cmd.UserBankCardCmd; +import com.red.circle.wallet.inner.model.cmd.UserWithdrawInfoCmd; import com.red.circle.wallet.inner.model.dto.UserBankBalanceDTO; import com.red.circle.wallet.inner.model.dto.UserBankCardDTO; import com.red.circle.wallet.inner.model.dto.UserBankRunningWaterDTO; import com.red.circle.wallet.inner.model.dto.UserBankWithdrawGoldApplyDTO; import com.red.circle.wallet.inner.model.dto.UserBankWithdrawMoneyApplyDTO; +import com.red.circle.wallet.inner.model.dto.UserWithdrawInfoDTO; import java.util.List; import java.util.Map; import org.mapstruct.Mapper; @@ -47,4 +50,13 @@ public interface UserBankInnerConvertor { UserBankCard toUserBankCard(UserBankCardCmd cmd); List toListUserBankCardDTO(List userBankCards); + + UserWithdrawInfoDTO toUserWithdrawInfoDTO(UserWithdrawInfo userWithdrawInfo); + + List toListUserWithdrawInfoDTO(List userWithdrawInfos); + + Map toMapUserWithdrawInfoDTO( + Map userWithdrawInfoMap); + + UserWithdrawInfo toUserWithdrawInfo(UserWithdrawInfoCmd cmd); }