From 0c5a038595271715e09287e6b7e4f8309ec33251 Mon Sep 17 00:00:00 2001 From: ziin Date: Fri, 26 Dec 2025 19:41:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(tenant-withdraw-order):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=A7=9F=E6=88=B7=E6=8F=90=E7=8E=B0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...KeyboardTenantWithdrawOrderController.java | 104 +++++++++++ .../KeyboardTenantWithdrawOrderPageReqVO.java | 114 ++++++++++++ .../vo/KeyboardTenantWithdrawOrderRespVO.java | 143 +++++++++++++++ .../KeyboardTenantWithdrawOrderSaveReqVO.java | 123 +++++++++++++ .../KeyboardTenantWithdrawOrderDO.java | 163 ++++++++++++++++++ .../KeyboardTenantWithdrawOrderMapper.java | 56 ++++++ .../KeyboardTenantWithdrawOrderService.java | 62 +++++++ ...eyboardTenantWithdrawOrderServiceImpl.java | 85 +++++++++ .../KeyboardTenantWithdrawOrderMapper.xml | 12 ++ .../infra/enums/ErrorCodeConstants.java | 1 + 10 files changed, 863 insertions(+) create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/KeyboardTenantWithdrawOrderController.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderPageReqVO.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderRespVO.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderSaveReqVO.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/dal/dataobject/tenantwithdraworder/KeyboardTenantWithdrawOrderDO.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/dal/mysql/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderService.java create mode 100644 keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderServiceImpl.java create mode 100644 keyboard-server/src/main/resources/mapper/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.xml diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/KeyboardTenantWithdrawOrderController.java b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/KeyboardTenantWithdrawOrderController.java new file mode 100644 index 0000000..e2a193f --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/KeyboardTenantWithdrawOrderController.java @@ -0,0 +1,104 @@ +package com.yolo.keyboard.controller.admin.tenantwithdraworder; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import com.yolo.keyboard.framework.common.pojo.PageParam; +import com.yolo.keyboard.framework.common.pojo.PageResult; +import com.yolo.keyboard.framework.common.pojo.CommonResult; +import com.yolo.keyboard.framework.common.util.object.BeanUtils; +import static com.yolo.keyboard.framework.common.pojo.CommonResult.success; + +import com.yolo.keyboard.framework.excel.core.util.ExcelUtils; + +import com.yolo.keyboard.framework.apilog.core.annotation.ApiAccessLog; +import static com.yolo.keyboard.framework.apilog.core.enums.OperateTypeEnum.*; + +import com.yolo.keyboard.controller.admin.tenantwithdraworder.vo.*; +import com.yolo.keyboard.dal.dataobject.tenantwithdraworder.KeyboardTenantWithdrawOrderDO; +import com.yolo.keyboard.service.tenantwithdraworder.KeyboardTenantWithdrawOrderService; + +@Tag(name = "管理后台 - 租户提现订单表(申请-审核-打款-完成/失败)") +@RestController +@RequestMapping("/keyboard/tenant-withdraw-order") +@Validated +public class KeyboardTenantWithdrawOrderController { + + @Resource + private KeyboardTenantWithdrawOrderService tenantWithdrawOrderService; + + @PostMapping("/create") + @Operation(summary = "创建租户提现订单表(申请-审核-打款-完成/失败)") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:create')") + public CommonResult createTenantWithdrawOrder(@Valid @RequestBody KeyboardTenantWithdrawOrderSaveReqVO createReqVO) { + return success(tenantWithdrawOrderService.createTenantWithdrawOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新租户提现订单表(申请-审核-打款-完成/失败)") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:update')") + public CommonResult updateTenantWithdrawOrder(@Valid @RequestBody KeyboardTenantWithdrawOrderSaveReqVO updateReqVO) { + tenantWithdrawOrderService.updateTenantWithdrawOrder(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除租户提现订单表(申请-审核-打款-完成/失败)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:delete')") + public CommonResult deleteTenantWithdrawOrder(@RequestParam("id") Long id) { + tenantWithdrawOrderService.deleteTenantWithdrawOrder(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Parameter(name = "ids", description = "编号", required = true) + @Operation(summary = "批量删除租户提现订单表(申请-审核-打款-完成/失败)") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:delete')") + public CommonResult deleteTenantWithdrawOrderList(@RequestParam("ids") List ids) { + tenantWithdrawOrderService.deleteTenantWithdrawOrderListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得租户提现订单表(申请-审核-打款-完成/失败)") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:query')") + public CommonResult getTenantWithdrawOrder(@RequestParam("id") Long id) { + KeyboardTenantWithdrawOrderDO tenantWithdrawOrder = tenantWithdrawOrderService.getTenantWithdrawOrder(id); + return success(BeanUtils.toBean(tenantWithdrawOrder, KeyboardTenantWithdrawOrderRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得租户提现订单表(申请-审核-打款-完成/失败)分页") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:query')") + public CommonResult> getTenantWithdrawOrderPage(@Valid KeyboardTenantWithdrawOrderPageReqVO pageReqVO) { + PageResult pageResult = tenantWithdrawOrderService.getTenantWithdrawOrderPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, KeyboardTenantWithdrawOrderRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出租户提现订单表(申请-审核-打款-完成/失败) Excel") + @PreAuthorize("@ss.hasPermission('keyboard:tenant-withdraw-order:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTenantWithdrawOrderExcel(@Valid KeyboardTenantWithdrawOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = tenantWithdrawOrderService.getTenantWithdrawOrderPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "租户提现订单表(申请-审核-打款-完成/失败).xls", "数据", KeyboardTenantWithdrawOrderRespVO.class, + BeanUtils.toBean(list, KeyboardTenantWithdrawOrderRespVO.class)); + } + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderPageReqVO.java b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderPageReqVO.java new file mode 100644 index 0000000..6a2a6ad --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderPageReqVO.java @@ -0,0 +1,114 @@ +package com.yolo.keyboard.controller.admin.tenantwithdraworder.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import com.yolo.keyboard.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static com.yolo.keyboard.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 租户提现订单表(申请-审核-打款-完成/失败)分页 Request VO") +@Data +public class KeyboardTenantWithdrawOrderPageReqVO extends PageParam { + + @Schema(description = "提现单号(业务唯一)") + private String withdrawNo; + + @Schema(description = "业务幂等号(防重复提交)") + private String bizNo; + + @Schema(description = "币种(默认 CNY)") + private String currency; + + @Schema(description = "提现申请金额(单位:分)") + private Long amount; + + @Schema(description = "手续费金额(单位:分)") + private Long feeAmount; + + @Schema(description = "实际到账金额(单位:分 = amount - fee_amount)") + private Long actualAmount; + + @Schema(description = "打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等") + private String payChannel; + + @Schema(description = "收款方类型:PERSON(个人)/COMPANY(企业)", example = "1") + private String payeeType; + + @Schema(description = "收款人姓名或公司名称(快照)", example = "张三") + private String payeeName; + + @Schema(description = "收款账号(银行卡/支付宝等,建议加密或脱敏)", example = "5425") + private String payeeAccount; + + @Schema(description = "收款银行名称", example = "芋艿") + private String payeeBankName; + + @Schema(description = "银行编码(可选)") + private String payeeBankCode; + + @Schema(description = "银行支行名称(可选)") + private String payeeBankBranch; + + @Schema(description = "提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED", example = "1") + private String status; + + @Schema(description = "审核状态:PENDING/PASSED/REJECTED", example = "1") + private String auditStatus; + + @Schema(description = "拒绝原因或打款失败原因", example = "不香") + private String reason; + + @Schema(description = "提现申请时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] applyTime; + + @Schema(description = "审核完成时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] auditTime; + + @Schema(description = "发起打款时间(请求第三方)") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] payTime; + + @Schema(description = "打款成功时间(第三方确认)") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] paidTime; + + @Schema(description = "业务终态时间(成功/失败/取消)") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] finishTime; + + @Schema(description = "打款批次号(内部使用)") + private String payerBatchNo; + + @Schema(description = "第三方打款交易号/流水号(对账用)") + private String channelTradeNo; + + @Schema(description = "第三方返回的原始报文(用于排查)") + private Object channelRaw; + + @Schema(description = "关联余额流水ID(冻结/扣减/返还)", example = "30641") + private Long balanceTxnId; + + @Schema(description = "乐观锁版本号") + private Integer version; + + @Schema(description = "提现申请人ID", example = "6858") + private Long creatorId; + + @Schema(description = "审核人ID", example = "15039") + private Long auditorId; + + @Schema(description = "打款操作人ID", example = "8850") + private Long payerId; + + @Schema(description = "创建时间") + private LocalDateTime createdAt; + + @Schema(description = "更新时间") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderRespVO.java b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderRespVO.java new file mode 100644 index 0000000..b21706a --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderRespVO.java @@ -0,0 +1,143 @@ +package com.yolo.keyboard.controller.admin.tenantwithdraworder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.idev.excel.annotation.*; + +@Schema(description = "管理后台 - 租户提现订单表(申请-审核-打款-完成/失败) Response VO") +@Data +@ExcelIgnoreUnannotated +public class KeyboardTenantWithdrawOrderRespVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "20442") + @ExcelProperty("主键") + private Long id; + + @Schema(description = "提现单号(业务唯一)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("提现单号(业务唯一)") + private String withdrawNo; + + @Schema(description = "业务幂等号(防重复提交)") + @ExcelProperty("业务幂等号(防重复提交)") + private String bizNo; + + @Schema(description = "币种(默认 CNY)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("币种(默认 CNY)") + private String currency; + + @Schema(description = "提现申请金额(单位:分)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("提现申请金额(单位:分)") + private Long amount; + + @Schema(description = "手续费金额(单位:分)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("手续费金额(单位:分)") + private Long feeAmount; + + @Schema(description = "实际到账金额(单位:分 = amount - fee_amount)", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("实际到账金额(单位:分 = amount - fee_amount)") + private Long actualAmount; + + @Schema(description = "打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等") + private String payChannel; + + @Schema(description = "收款方类型:PERSON(个人)/COMPANY(企业)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("收款方类型:PERSON(个人)/COMPANY(企业)") + private String payeeType; + + @Schema(description = "收款人姓名或公司名称(快照)", example = "张三") + @ExcelProperty("收款人姓名或公司名称(快照)") + private String payeeName; + + @Schema(description = "收款账号(银行卡/支付宝等,建议加密或脱敏)", example = "5425") + @ExcelProperty("收款账号(银行卡/支付宝等,建议加密或脱敏)") + private String payeeAccount; + + @Schema(description = "收款银行名称", example = "芋艿") + @ExcelProperty("收款银行名称") + private String payeeBankName; + + @Schema(description = "银行编码(可选)") + @ExcelProperty("银行编码(可选)") + private String payeeBankCode; + + @Schema(description = "银行支行名称(可选)") + @ExcelProperty("银行支行名称(可选)") + private String payeeBankBranch; + + @Schema(description = "提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED") + private String status; + + @Schema(description = "审核状态:PENDING/PASSED/REJECTED", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("审核状态:PENDING/PASSED/REJECTED") + private String auditStatus; + + @Schema(description = "拒绝原因或打款失败原因", example = "不香") + @ExcelProperty("拒绝原因或打款失败原因") + private String reason; + + @Schema(description = "提现申请时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("提现申请时间") + private LocalDateTime applyTime; + + @Schema(description = "审核完成时间") + @ExcelProperty("审核完成时间") + private LocalDateTime auditTime; + + @Schema(description = "发起打款时间(请求第三方)") + @ExcelProperty("发起打款时间(请求第三方)") + private LocalDateTime payTime; + + @Schema(description = "打款成功时间(第三方确认)") + @ExcelProperty("打款成功时间(第三方确认)") + private LocalDateTime paidTime; + + @Schema(description = "业务终态时间(成功/失败/取消)") + @ExcelProperty("业务终态时间(成功/失败/取消)") + private LocalDateTime finishTime; + + @Schema(description = "打款批次号(内部使用)") + @ExcelProperty("打款批次号(内部使用)") + private String payerBatchNo; + + @Schema(description = "第三方打款交易号/流水号(对账用)") + @ExcelProperty("第三方打款交易号/流水号(对账用)") + private String channelTradeNo; + + @Schema(description = "第三方返回的原始报文(用于排查)") + @ExcelProperty("第三方返回的原始报文(用于排查)") + private Object channelRaw; + + @Schema(description = "关联余额流水ID(冻结/扣减/返还)", example = "30641") + @ExcelProperty("关联余额流水ID(冻结/扣减/返还)") + private Long balanceTxnId; + + @Schema(description = "乐观锁版本号", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("乐观锁版本号") + private Integer version; + + @Schema(description = "提现申请人ID", example = "6858") + @ExcelProperty("提现申请人ID") + private Long creatorId; + + @Schema(description = "审核人ID", example = "15039") + @ExcelProperty("审核人ID") + private Long auditorId; + + @Schema(description = "打款操作人ID", example = "8850") + @ExcelProperty("打款操作人ID") + private Long payerId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createdAt; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderSaveReqVO.java b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderSaveReqVO.java new file mode 100644 index 0000000..1924454 --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/controller/admin/tenantwithdraworder/vo/KeyboardTenantWithdrawOrderSaveReqVO.java @@ -0,0 +1,123 @@ +package com.yolo.keyboard.controller.admin.tenantwithdraworder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 租户提现订单表(申请-审核-打款-完成/失败)新增/修改 Request VO") +@Data +public class KeyboardTenantWithdrawOrderSaveReqVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "20442") + private Long id; + + @Schema(description = "提现单号(业务唯一)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "提现单号(业务唯一)不能为空") + private String withdrawNo; + + @Schema(description = "业务幂等号(防重复提交)") + private String bizNo; + + @Schema(description = "币种(默认 CNY)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "币种(默认 CNY)不能为空") + private String currency; + + @Schema(description = "提现申请金额(单位:分)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "提现申请金额(单位:分)不能为空") + private Long amount; + + @Schema(description = "手续费金额(单位:分)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "手续费金额(单位:分)不能为空") + private Long feeAmount; + + @Schema(description = "实际到账金额(单位:分 = amount - fee_amount)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "实际到账金额(单位:分 = amount - fee_amount)不能为空") + private Long actualAmount; + + @Schema(description = "打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等不能为空") + private String payChannel; + + @Schema(description = "收款方类型:PERSON(个人)/COMPANY(企业)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "收款方类型:PERSON(个人)/COMPANY(企业)不能为空") + private String payeeType; + + @Schema(description = "收款人姓名或公司名称(快照)", example = "张三") + private String payeeName; + + @Schema(description = "收款账号(银行卡/支付宝等,建议加密或脱敏)", example = "5425") + private String payeeAccount; + + @Schema(description = "收款银行名称", example = "芋艿") + private String payeeBankName; + + @Schema(description = "银行编码(可选)") + private String payeeBankCode; + + @Schema(description = "银行支行名称(可选)") + private String payeeBankBranch; + + @Schema(description = "提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED不能为空") + private String status; + + @Schema(description = "审核状态:PENDING/PASSED/REJECTED", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "审核状态:PENDING/PASSED/REJECTED不能为空") + private String auditStatus; + + @Schema(description = "拒绝原因或打款失败原因", example = "不香") + private String reason; + + @Schema(description = "提现申请时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "提现申请时间不能为空") + private LocalDateTime applyTime; + + @Schema(description = "审核完成时间") + private LocalDateTime auditTime; + + @Schema(description = "发起打款时间(请求第三方)") + private LocalDateTime payTime; + + @Schema(description = "打款成功时间(第三方确认)") + private LocalDateTime paidTime; + + @Schema(description = "业务终态时间(成功/失败/取消)") + private LocalDateTime finishTime; + + @Schema(description = "打款批次号(内部使用)") + private String payerBatchNo; + + @Schema(description = "第三方打款交易号/流水号(对账用)") + private String channelTradeNo; + + @Schema(description = "第三方返回的原始报文(用于排查)") + private Object channelRaw; + + @Schema(description = "关联余额流水ID(冻结/扣减/返还)", example = "30641") + private Long balanceTxnId; + + @Schema(description = "乐观锁版本号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "乐观锁版本号不能为空") + private Integer version; + + @Schema(description = "提现申请人ID", example = "6858") + private Long creatorId; + + @Schema(description = "审核人ID", example = "15039") + private Long auditorId; + + @Schema(description = "打款操作人ID", example = "8850") + private Long payerId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "创建时间不能为空") + private LocalDateTime createdAt; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "更新时间不能为空") + private LocalDateTime updatedAt; + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/dal/dataobject/tenantwithdraworder/KeyboardTenantWithdrawOrderDO.java b/keyboard-server/src/main/java/com/yolo/keyboard/dal/dataobject/tenantwithdraworder/KeyboardTenantWithdrawOrderDO.java new file mode 100644 index 0000000..f94f749 --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/dal/dataobject/tenantwithdraworder/KeyboardTenantWithdrawOrderDO.java @@ -0,0 +1,163 @@ +package com.yolo.keyboard.dal.dataobject.tenantwithdraworder; + +import com.yolo.keyboard.framework.tenant.core.aop.TenantIgnore; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import com.yolo.keyboard.framework.mybatis.core.dataobject.BaseDO; + +/** + * 租户提现订单表(申请-审核-打款-完成/失败) DO + * + * @author ziin + */ +@TableName("system_tenant_withdraw_order") +@KeySequence("system_tenant_withdraw_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TenantIgnore +public class KeyboardTenantWithdrawOrderDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 提现单号(业务唯一) + */ + private String withdrawNo; + /** + * 业务幂等号(防重复提交) + */ + private String bizNo; + /** + * 币种(默认 CNY) + */ + private String currency; + /** + * 提现申请金额(单位:分) + */ + private Long amount; + /** + * 手续费金额(单位:分) + */ + private Long feeAmount; + /** + * 实际到账金额(单位:分 = amount - fee_amount) + */ + private Long actualAmount; + /** + * 打款渠道:BANK/ALIPAY/WECHAT/PAYPAL 等 + */ + private String payChannel; + /** + * 收款方类型:PERSON(个人)/COMPANY(企业) + */ + private String payeeType; + /** + * 收款人姓名或公司名称(快照) + */ + private String payeeName; + /** + * 收款账号(银行卡/支付宝等,建议加密或脱敏) + */ + private String payeeAccount; + /** + * 收款银行名称 + */ + private String payeeBankName; + /** + * 银行编码(可选) + */ + private String payeeBankCode; + /** + * 银行支行名称(可选) + */ + private String payeeBankBranch; + /** + * 提现状态:APPLIED/APPROVED/REJECTED/PAYING/PAID/FAILED/CANCELED + */ + private String status; + /** + * 审核状态:PENDING/PASSED/REJECTED + */ + private String auditStatus; + /** + * 拒绝原因或打款失败原因 + */ + private String reason; + /** + * 提现申请时间 + */ + private LocalDateTime applyTime; + /** + * 审核完成时间 + */ + private LocalDateTime auditTime; + /** + * 发起打款时间(请求第三方) + */ + private LocalDateTime payTime; + /** + * 打款成功时间(第三方确认) + */ + private LocalDateTime paidTime; + /** + * 业务终态时间(成功/失败/取消) + */ + private LocalDateTime finishTime; + /** + * 打款批次号(内部使用) + */ + private String payerBatchNo; + /** + * 第三方打款交易号/流水号(对账用) + */ + private String channelTradeNo; + /** + * 第三方返回的原始报文(用于排查) + */ + private Object channelRaw; + /** + * 关联余额流水ID(冻结/扣减/返还) + */ + private Long balanceTxnId; + /** + * 乐观锁版本号 + */ + private Integer version; + /** + * 提现申请人ID + */ + private Long creatorId; + /** + * 审核人ID + */ + private Long auditorId; + /** + * 打款操作人ID + */ + private Long payerId; + /** + * 创建时间 + */ + private LocalDateTime createdAt; + /** + * 更新时间 + */ + private LocalDateTime updatedAt; + + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/dal/mysql/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.java b/keyboard-server/src/main/java/com/yolo/keyboard/dal/mysql/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.java new file mode 100644 index 0000000..d0c5eec --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/dal/mysql/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.java @@ -0,0 +1,56 @@ +package com.yolo.keyboard.dal.mysql.tenantwithdraworder; + +import java.util.*; + +import com.yolo.keyboard.framework.common.pojo.PageResult; +import com.yolo.keyboard.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.yolo.keyboard.framework.mybatis.core.mapper.BaseMapperX; +import com.yolo.keyboard.dal.dataobject.tenantwithdraworder.KeyboardTenantWithdrawOrderDO; +import org.apache.ibatis.annotations.Mapper; +import com.yolo.keyboard.controller.admin.tenantwithdraworder.vo.*; + +/** + * 租户提现订单表(申请-审核-打款-完成/失败) Mapper + * + * @author ziin + */ +@Mapper +public interface KeyboardTenantWithdrawOrderMapper extends BaseMapperX { + + default PageResult selectPage(KeyboardTenantWithdrawOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getWithdrawNo, reqVO.getWithdrawNo()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getBizNo, reqVO.getBizNo()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getCurrency, reqVO.getCurrency()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getAmount, reqVO.getAmount()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getFeeAmount, reqVO.getFeeAmount()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getActualAmount, reqVO.getActualAmount()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayChannel, reqVO.getPayChannel()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeType, reqVO.getPayeeType()) + .likeIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeName, reqVO.getPayeeName()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeAccount, reqVO.getPayeeAccount()) + .likeIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeBankName, reqVO.getPayeeBankName()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeBankCode, reqVO.getPayeeBankCode()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayeeBankBranch, reqVO.getPayeeBankBranch()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getStatus, reqVO.getStatus()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getAuditStatus, reqVO.getAuditStatus()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getReason, reqVO.getReason()) + .betweenIfPresent(KeyboardTenantWithdrawOrderDO::getApplyTime, reqVO.getApplyTime()) + .betweenIfPresent(KeyboardTenantWithdrawOrderDO::getAuditTime, reqVO.getAuditTime()) + .betweenIfPresent(KeyboardTenantWithdrawOrderDO::getPayTime, reqVO.getPayTime()) + .betweenIfPresent(KeyboardTenantWithdrawOrderDO::getPaidTime, reqVO.getPaidTime()) + .betweenIfPresent(KeyboardTenantWithdrawOrderDO::getFinishTime, reqVO.getFinishTime()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayerBatchNo, reqVO.getPayerBatchNo()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getChannelTradeNo, reqVO.getChannelTradeNo()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getChannelRaw, reqVO.getChannelRaw()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getBalanceTxnId, reqVO.getBalanceTxnId()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getVersion, reqVO.getVersion()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getCreatorId, reqVO.getCreatorId()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getAuditorId, reqVO.getAuditorId()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getPayerId, reqVO.getPayerId()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getCreatedAt, reqVO.getCreatedAt()) + .eqIfPresent(KeyboardTenantWithdrawOrderDO::getUpdatedAt, reqVO.getUpdatedAt()) + .orderByDesc(KeyboardTenantWithdrawOrderDO::getId)); + } + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderService.java b/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderService.java new file mode 100644 index 0000000..823b729 --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderService.java @@ -0,0 +1,62 @@ +package com.yolo.keyboard.service.tenantwithdraworder; + +import java.util.*; +import jakarta.validation.*; +import com.yolo.keyboard.controller.admin.tenantwithdraworder.vo.*; +import com.yolo.keyboard.dal.dataobject.tenantwithdraworder.KeyboardTenantWithdrawOrderDO; +import com.yolo.keyboard.framework.common.pojo.PageResult; +import com.yolo.keyboard.framework.common.pojo.PageParam; + +/** + * 租户提现订单表(申请-审核-打款-完成/失败) Service 接口 + * + * @author ziin + */ +public interface KeyboardTenantWithdrawOrderService { + + /** + * 创建租户提现订单表(申请-审核-打款-完成/失败) + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTenantWithdrawOrder(@Valid KeyboardTenantWithdrawOrderSaveReqVO createReqVO); + + /** + * 更新租户提现订单表(申请-审核-打款-完成/失败) + * + * @param updateReqVO 更新信息 + */ + void updateTenantWithdrawOrder(@Valid KeyboardTenantWithdrawOrderSaveReqVO updateReqVO); + + /** + * 删除租户提现订单表(申请-审核-打款-完成/失败) + * + * @param id 编号 + */ + void deleteTenantWithdrawOrder(Long id); + + /** + * 批量删除租户提现订单表(申请-审核-打款-完成/失败) + * + * @param ids 编号 + */ + void deleteTenantWithdrawOrderListByIds(List ids); + + /** + * 获得租户提现订单表(申请-审核-打款-完成/失败) + * + * @param id 编号 + * @return 租户提现订单表(申请-审核-打款-完成/失败) + */ + KeyboardTenantWithdrawOrderDO getTenantWithdrawOrder(Long id); + + /** + * 获得租户提现订单表(申请-审核-打款-完成/失败)分页 + * + * @param pageReqVO 分页查询 + * @return 租户提现订单表(申请-审核-打款-完成/失败)分页 + */ + PageResult getTenantWithdrawOrderPage(KeyboardTenantWithdrawOrderPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderServiceImpl.java b/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderServiceImpl.java new file mode 100644 index 0000000..b6cbe32 --- /dev/null +++ b/keyboard-server/src/main/java/com/yolo/keyboard/service/tenantwithdraworder/KeyboardTenantWithdrawOrderServiceImpl.java @@ -0,0 +1,85 @@ +package com.yolo.keyboard.service.tenantwithdraworder; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import com.yolo.keyboard.controller.admin.tenantwithdraworder.vo.*; +import com.yolo.keyboard.dal.dataobject.tenantwithdraworder.KeyboardTenantWithdrawOrderDO; +import com.yolo.keyboard.framework.common.pojo.PageResult; +import com.yolo.keyboard.framework.common.pojo.PageParam; +import com.yolo.keyboard.framework.common.util.object.BeanUtils; + +import com.yolo.keyboard.dal.mysql.tenantwithdraworder.KeyboardTenantWithdrawOrderMapper; + +import static com.yolo.keyboard.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.yolo.keyboard.framework.common.util.collection.CollectionUtils.convertList; +import static com.yolo.keyboard.framework.common.util.collection.CollectionUtils.diffList; +import static com.yolo.keyboard.module.infra.enums.ErrorCodeConstants.TENANT_WITHDRAW_ORDER_NOT_EXISTS; + +/** + * 租户提现订单表(申请-审核-打款-完成/失败) Service 实现类 + * + * @author ziin + */ +@Service +@Validated +public class KeyboardTenantWithdrawOrderServiceImpl implements KeyboardTenantWithdrawOrderService { + + @Resource + private KeyboardTenantWithdrawOrderMapper tenantWithdrawOrderMapper; + + @Override + public Long createTenantWithdrawOrder(KeyboardTenantWithdrawOrderSaveReqVO createReqVO) { + // 插入 + KeyboardTenantWithdrawOrderDO tenantWithdrawOrder = BeanUtils.toBean(createReqVO, KeyboardTenantWithdrawOrderDO.class); + tenantWithdrawOrderMapper.insert(tenantWithdrawOrder); + + // 返回 + return tenantWithdrawOrder.getId(); + } + + @Override + public void updateTenantWithdrawOrder(KeyboardTenantWithdrawOrderSaveReqVO updateReqVO) { + // 校验存在 + validateTenantWithdrawOrderExists(updateReqVO.getId()); + // 更新 + KeyboardTenantWithdrawOrderDO updateObj = BeanUtils.toBean(updateReqVO, KeyboardTenantWithdrawOrderDO.class); + tenantWithdrawOrderMapper.updateById(updateObj); + } + + @Override + public void deleteTenantWithdrawOrder(Long id) { + // 校验存在 + validateTenantWithdrawOrderExists(id); + // 删除 + tenantWithdrawOrderMapper.deleteById(id); + } + + @Override + public void deleteTenantWithdrawOrderListByIds(List ids) { + // 删除 + tenantWithdrawOrderMapper.deleteByIds(ids); + } + + + private void validateTenantWithdrawOrderExists(Long id) { + if (tenantWithdrawOrderMapper.selectById(id) == null) { + throw exception(TENANT_WITHDRAW_ORDER_NOT_EXISTS); + } + } + + @Override + public KeyboardTenantWithdrawOrderDO getTenantWithdrawOrder(Long id) { + return tenantWithdrawOrderMapper.selectById(id); + } + + @Override + public PageResult getTenantWithdrawOrderPage(KeyboardTenantWithdrawOrderPageReqVO pageReqVO) { + return tenantWithdrawOrderMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/keyboard-server/src/main/resources/mapper/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.xml b/keyboard-server/src/main/resources/mapper/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.xml new file mode 100644 index 0000000..5d00beb --- /dev/null +++ b/keyboard-server/src/main/resources/mapper/tenantwithdraworder/KeyboardTenantWithdrawOrderMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yolo-module-infra/src/main/java/com/yolo/keyboard/module/infra/enums/ErrorCodeConstants.java b/yolo-module-infra/src/main/java/com/yolo/keyboard/module/infra/enums/ErrorCodeConstants.java index 4043207..ec90fd5 100644 --- a/yolo-module-infra/src/main/java/com/yolo/keyboard/module/infra/enums/ErrorCodeConstants.java +++ b/yolo-module-infra/src/main/java/com/yolo/keyboard/module/infra/enums/ErrorCodeConstants.java @@ -90,6 +90,7 @@ public interface ErrorCodeConstants { ErrorCode TENANT_BALANCE_WITHDRAW_NOT_IN_DATE = new ErrorCode(1_001_202_016, "当前不在提现日期范围内"); ErrorCode TENANT_BALANCE_WITHDRAW_INSUFFICIENT = new ErrorCode(1_001_202_017, "余额不足,无法提现"); ErrorCode TENANT_BALANCE_WITHDRAW_CONFIG_NOT_EXISTS = new ErrorCode(1_001_202_018, "提现配置不存在"); + ErrorCode TENANT_WITHDRAW_ORDER_NOT_EXISTS = new ErrorCode(1_001_202_019, "租户提现订单表(申请-审核-打款-完成/失败)不存在"); }