Procházet zdrojové kódy

!624 trade: 分销业务 - 佣金提现
Merge pull request !624 from 疯狂的世界/brokerate

芋道源码 před 1 rokem
rodič
revize
de7699d972
16 změnil soubory, kde provedl 717 přidání a 8 odebrání
  1. 13 7
      sql/mysql/brokerage.sql
  2. 5 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
  3. 3 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java
  4. 82 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/BrokerageWithdrawController.java
  5. 23 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawAuditReqVO.java
  6. 68 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawBaseVO.java
  7. 47 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawPageReqVO.java
  8. 25 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawRespVO.java
  9. 40 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/withdraw/BrokerageWithdrawConvert.java
  10. 94 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/withdraw/BrokerageWithdrawDO.java
  11. 36 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/withdraw/BrokerageWithdrawMapper.java
  12. 51 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/withdraw/BrokerageWithdrawService.java
  13. 116 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/withdraw/BrokerageWithdrawServiceImpl.java
  14. 87 0
      yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/withdraw/BrokerageWithdrawServiceImplTest.java
  15. 1 0
      yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql
  16. 26 1
      yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql

+ 13 - 7
sql/mysql/brokerage.sql

@@ -148,12 +148,12 @@ values ('brokerage_record_status', '待结算', 0, 0),
 
 insert into system_dict_type(type, name)
 values ('brokerage_withdraw_status', '佣金提现状态');
-insert into system_dict_data(dict_type, label, value, sort)
-values ('brokerage_withdraw_status', '审核中', 0, 0),
-       ('brokerage_withdraw_status', '审核通过', 10, 10),
-       ('brokerage_withdraw_status', '提现成功', 11, 11),
-       ('brokerage_withdraw_status', '审核不通过', 20, 20),
-       ('brokerage_withdraw_status', '提现失败', 21, 21);
+insert into system_dict_data(dict_type, label, value, sort, color_type)
+values ('brokerage_withdraw_status', '审核中', 0, 0, ''),
+       ('brokerage_withdraw_status', '审核通过', 10, 10, 'success'),
+       ('brokerage_withdraw_status', '提现成功', 11, 11, 'success'),
+       ('brokerage_withdraw_status', '审核不通过', 20, 20, 'danger'),
+       ('brokerage_withdraw_status', '提现失败', 21, 21, 'danger');
 
 insert into system_dict_type(type, name)
 values ('brokerage_bank_name', '佣金提现银行');
@@ -229,4 +229,10 @@ SELECT @parentId := LAST_INSERT_ID();
 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
 VALUES ('佣金提现查询', 'trade:brokerage-withdraw:query', 3, 1, @parentId, '', '', '', 0);
 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
-VALUES ('佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, @parentId, '', '', '', 0);
+VALUES ('佣金提现审核', 'trade:brokerage-withdraw:audit', 3, 2, @parentId, '', '', '', 0);
+
+-- 站内信模板
+INSERT INTO `ruoyi-vue-pro`.system_notify_template (name, code, nickname, content, type, params, status)
+VALUES
+    ('佣金提现(审核通过)', 'brokerage_withdraw_audit_approve', 'system', '您在{createTime}提现¥{price}元的申请已通过审核', 2, '["createTime","price"]', 0),
+    ('佣金提现(审核不通过)', 'brokerage_withdraw_audit_reject', 'system', '您在{createTime}提现¥{price}元的申请未通过审核,原因:{reason}', 2, '["createTime","price","reason"]', 0);

+ 5 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java

@@ -88,4 +88,9 @@ public interface ErrorCodeConstants {
     ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人");
     ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级");
 
+
+    // ========== 分销提现 模块 1011008000 ==========
+    ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1011008000, "佣金提现记录不存在");
+    ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1011008001, "佣金提现记录状态不是审核中");
+
 }

+ 3 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java

@@ -10,4 +10,7 @@ public interface MessageTemplateConstants {
 
     String ORDER_DELIVERY = "order_delivery"; // 短信模版编号
 
+    String BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过)
+    String BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过)
+
 }

+ 82 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/BrokerageWithdrawController.java

@@ -0,0 +1,82 @@
+package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawAuditReqVO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRespVO;
+import cn.iocoder.yudao.module.trade.convert.brokerage.withdraw.BrokerageWithdrawConvert;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+import cn.iocoder.yudao.module.trade.service.brokerage.withdraw.BrokerageWithdrawService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import java.util.Map;
+import java.util.Set;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+@Tag(name = "管理后台 - 佣金提现")
+@RestController
+@RequestMapping("/trade/brokerage-withdraw")
+@Validated
+public class BrokerageWithdrawController {
+
+    @Resource
+    private BrokerageWithdrawService brokerageWithdrawService;
+
+    @Resource
+    private MemberUserApi memberUserApi;
+
+    @PutMapping("/approve")
+    @Operation(summary = "佣金提现 - 通过申请")
+    @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
+    public CommonResult<Boolean> approveBrokerageWithdraw(@RequestParam("id") Integer id) {
+        brokerageWithdrawService.auditBrokerageWithdraw(id, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, "");
+        return success(true);
+    }
+
+    @PutMapping("/reject")
+    @Operation(summary = "审核佣金提现 - 驳回申请")
+    @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:audit')")
+    public CommonResult<Boolean> rejectBrokerageWithdraw(@Valid @RequestBody BrokerageWithdrawAuditReqVO reqVO) {
+        brokerageWithdrawService.auditBrokerageWithdraw(reqVO.getId(), BrokerageWithdrawStatusEnum.AUDIT_FAIL, reqVO.getAuditReason());
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得佣金提现")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')")
+    public CommonResult<BrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Integer id) {
+        BrokerageWithdrawDO brokerageWithdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
+        return success(BrokerageWithdrawConvert.INSTANCE.convert(brokerageWithdraw));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得佣金提现分页")
+    @PreAuthorize("@ss.hasPermission('trade:brokerage-withdraw:query')")
+    public CommonResult<PageResult<BrokerageWithdrawRespVO>> getBrokerageWithdrawPage(@Valid BrokerageWithdrawPageReqVO pageVO) {
+        // 分页查询
+        PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(pageVO);
+
+        // 涉及到的用户
+        Set<Long> userIds = convertSet(pageResult.getList(), BrokerageWithdrawDO::getUserId);
+        // 查询用户信息
+        Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
+
+        return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
+    }
+
+}

+ 23 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawAuditReqVO.java

@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 佣金提现审核 Request VO")
+@Data
+@ToString(callSuper = true)
+public class BrokerageWithdrawAuditReqVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
+    @NotNull(message = "编号不能为空")
+    private Integer id;
+
+    @Schema(description = "审核驳回原因", example = "不对")
+    @NotEmpty(message = "审核驳回原因不能为空")
+    private String auditReason;
+
+}

+ 68 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawBaseVO.java

@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 佣金提现 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+ */
+@Data
+public class BrokerageWithdrawBaseVO {
+
+    @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11436")
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
+
+    @Schema(description = "提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "18781")
+    @NotNull(message = "提现金额不能为空")
+    private Integer price;
+
+    @Schema(description = "提现手续费", requiredMode = Schema.RequiredMode.REQUIRED, example = "11417")
+    @NotNull(message = "提现手续费不能为空")
+    private Integer feePrice;
+
+    @Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "18576")
+    @NotNull(message = "当前总佣金不能为空")
+    private Integer totalPrice;
+
+    @Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "提现类型不能为空")
+    private Integer type;
+
+    @Schema(description = "真实姓名", example = "赵六")
+    private String name;
+
+    @Schema(description = "账号")
+    private String accountNo;
+
+    @Schema(description = "银行名称", example = "1")
+    private String bankName;
+
+    @Schema(description = "开户地址", example = "海淀支行")
+    private String bankAddress;
+
+    @Schema(description = "收款码", example = "https://www.iocoder.cn")
+    private String accountQrCodeUrl;
+
+    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "状态不能为空")
+    private Integer status;
+
+    @Schema(description = "审核驳回原因", example = "不对")
+    private String auditReason;
+
+    @Schema(description = "审核时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime auditTime;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
+}

+ 47 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawPageReqVO.java

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 佣金提现分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BrokerageWithdrawPageReqVO extends PageParam {
+
+    @Schema(description = "用户编号", example = "11436")
+    private Long userId;
+
+    @Schema(description = "提现类型", example = "1")
+    @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现类型必须是 {value}")
+    private Integer type;
+
+    @Schema(description = "真实姓名", example = "赵六")
+    private String name;
+
+    @Schema(description = "账号")
+    private String accountNo;
+
+    @Schema(description = "银行名称", example = "1")
+    private String bankName;
+
+    @Schema(description = "状态", example = "1")
+    @InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 25 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawRespVO.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 佣金提现 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
+    private Integer id;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+    @Schema(description = "用户昵称")
+    private String userNickname;
+
+}

+ 40 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/withdraw/BrokerageWithdrawConvert.java

@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.trade.convert.brokerage.withdraw;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawAuditReqVO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRespVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * 佣金提现 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface BrokerageWithdrawConvert {
+
+    BrokerageWithdrawConvert INSTANCE = Mappers.getMapper(BrokerageWithdrawConvert.class);
+
+    BrokerageWithdrawDO convert(BrokerageWithdrawAuditReqVO bean);
+
+    BrokerageWithdrawRespVO convert(BrokerageWithdrawDO bean);
+
+    List<BrokerageWithdrawRespVO> convertList(List<BrokerageWithdrawDO> list);
+
+    PageResult<BrokerageWithdrawRespVO> convertPage(PageResult<BrokerageWithdrawDO> page);
+
+    default PageResult<BrokerageWithdrawRespVO> convertPage(PageResult<BrokerageWithdrawDO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
+        PageResult<BrokerageWithdrawRespVO> result = convertPage(pageResult);
+        for (BrokerageWithdrawRespVO vo : result.getList()) {
+            vo.setUserNickname(Optional.ofNullable(userMap.get(vo.getUserId())).map(MemberUserRespDTO::getNickname).orElse(""));
+        }
+        return result;
+    }
+}

+ 94 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/withdraw/BrokerageWithdrawDO.java

@@ -0,0 +1,94 @@
+package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * 佣金提现 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("trade_brokerage_withdraw")
+@KeySequence("trade_brokerage_withdraw_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BrokerageWithdrawDO extends BaseDO {
+
+    /**
+     * 编号
+     */
+    @TableId
+    private Integer id;
+    /**
+     * 用户编号
+     */
+    private Long userId;
+    /**
+     * 提现金额
+     */
+    private Integer price;
+    /**
+     * 提现手续费
+     */
+    private Integer feePrice;
+    /**
+     * 当前总佣金
+     */
+    private Integer totalPrice;
+    /**
+     * 提现类型
+     * <p>
+     * 枚举 {@link BrokerageWithdrawTypeEnum}
+     */
+    private Integer type;
+    /**
+     * 真实姓名
+     */
+    private String name;
+    /**
+     * 账号
+     */
+    private String accountNo;
+    /**
+     * 银行名称
+     */
+    private String bankName;
+    /**
+     * 开户地址
+     */
+    private String bankAddress;
+    /**
+     * 收款码
+     */
+    private String accountQrCodeUrl;
+    /**
+     * 状态
+     * <p>
+     * 枚举 {@link BrokerageWithdrawStatusEnum}
+     */
+    private Integer status;
+    /**
+     * 审核驳回原因
+     */
+    private String auditReason;
+    /**
+     * 审核时间
+     */
+    private LocalDateTime auditTime;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 36 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/withdraw/BrokerageWithdrawMapper.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.withdraw;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 佣金提现 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO> {
+
+    default PageResult<BrokerageWithdrawDO> selectPage(BrokerageWithdrawPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageWithdrawDO>()
+                .eqIfPresent(BrokerageWithdrawDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(BrokerageWithdrawDO::getType, reqVO.getType())
+                .likeIfPresent(BrokerageWithdrawDO::getName, reqVO.getName())
+                .eqIfPresent(BrokerageWithdrawDO::getAccountNo, reqVO.getAccountNo())
+                .likeIfPresent(BrokerageWithdrawDO::getBankName, reqVO.getBankName())
+                .eqIfPresent(BrokerageWithdrawDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(BrokerageWithdrawDO::getCreateTime, reqVO.getCreateTime())
+                .orderByAsc(BrokerageWithdrawDO::getStatus).orderByDesc(BrokerageWithdrawDO::getId));
+    }
+
+    default int updateByIdAndStatus(Integer id, Integer status, BrokerageWithdrawDO updateObj) {
+        return update(updateObj, new LambdaUpdateWrapper<BrokerageWithdrawDO>()
+                .eq(BrokerageWithdrawDO::getId, id)
+                .eq(BrokerageWithdrawDO::getStatus, status));
+    }
+}

+ 51 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/withdraw/BrokerageWithdrawService.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.trade.service.brokerage.withdraw;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 佣金提现 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface BrokerageWithdrawService {
+
+    /**
+     * 审核佣金提现
+     *
+     * @param id          佣金编号
+     * @param status      审核状态
+     * @param auditReason 驳回原因
+     */
+
+    void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason);
+
+    /**
+     * 获得佣金提现
+     *
+     * @param id 编号
+     * @return 佣金提现
+     */
+    BrokerageWithdrawDO getBrokerageWithdraw(Integer id);
+
+    /**
+     * 获得佣金提现列表
+     *
+     * @param ids 编号
+     * @return 佣金提现列表
+     */
+    List<BrokerageWithdrawDO> getBrokerageWithdrawList(Collection<Integer> ids);
+
+    /**
+     * 获得佣金提现分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 佣金提现分页
+     */
+    PageResult<BrokerageWithdrawDO> getBrokerageWithdrawPage(BrokerageWithdrawPageReqVO pageReqVO);
+}

+ 116 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/withdraw/BrokerageWithdrawServiceImpl.java

@@ -0,0 +1,116 @@
+package cn.iocoder.yudao.module.trade.service.brokerage.withdraw;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
+import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.withdraw.BrokerageWithdrawMapper;
+import cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
+import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_WITHDRAW_NOT_EXISTS;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING;
+
+/**
+ * 佣金提现 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
+
+    @Resource
+    private BrokerageWithdrawMapper brokerageWithdrawMapper;
+
+    @Resource
+    private BrokerageRecordService brokerageRecordService;
+
+    @Resource
+    private NotifyMessageSendApi notifyMessageSendApi;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void auditBrokerageWithdraw(Integer id, BrokerageWithdrawStatusEnum status, String auditReason) {
+
+        // 校验存在
+        BrokerageWithdrawDO withdrawDO = validateBrokerageWithdrawExists(id);
+        // 校验状态为审核中
+        if (!BrokerageWithdrawStatusEnum.AUDITING.getStatus().equals(withdrawDO.getStatus())) {
+            throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
+        }
+
+        // 更新
+        BrokerageWithdrawDO updateObj = new BrokerageWithdrawDO()
+                .setStatus(status.getStatus())
+                .setAuditReason(auditReason)
+                .setAuditTime(LocalDateTime.now());
+        int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(), updateObj);
+        if (rows == 0) {
+            throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
+        }
+
+        // 驳回时需要退还用户佣金
+        String templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_APPROVE;
+        if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
+            templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_REJECT;
+
+            // todo @owen
+//            brokerageRecordService.addBrokerage(withdrawDO.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW, withdrawDO.getPrice(), "");
+        }
+
+        // 通知用户
+        Map<String, Object> templateParams = MapUtil.<String, Object>builder()
+                .put("createTime", LocalDateTimeUtil.formatNormal(withdrawDO.getCreateTime()))
+                .put("price", String.format("%.2f", withdrawDO.getPrice() / 100d))
+                .put("reason", withdrawDO.getAuditReason())
+                .build();
+        NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO()
+                .setUserId(withdrawDO.getUserId())
+                .setTemplateCode(templateCode).setTemplateParams(templateParams);
+        notifyMessageSendApi.sendSingleMessageToMember(reqDTO);
+    }
+
+    private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) {
+        BrokerageWithdrawDO withdrawDO = brokerageWithdrawMapper.selectById(id);
+        if (withdrawDO == null) {
+            throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS);
+        }
+        return withdrawDO;
+    }
+
+    @Override
+    public BrokerageWithdrawDO getBrokerageWithdraw(Integer id) {
+        return brokerageWithdrawMapper.selectById(id);
+    }
+
+    @Override
+    public List<BrokerageWithdrawDO> getBrokerageWithdrawList(Collection<Integer> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return ListUtil.empty();
+        }
+        return brokerageWithdrawMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<BrokerageWithdrawDO> getBrokerageWithdrawPage(BrokerageWithdrawPageReqVO pageReqVO) {
+        return brokerageWithdrawMapper.selectPage(pageReqVO);
+    }
+
+}

+ 87 - 0
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/withdraw/BrokerageWithdrawServiceImplTest.java

@@ -0,0 +1,87 @@
+package cn.iocoder.yudao.module.trade.service.withdraw;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
+import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.withdraw.BrokerageWithdrawMapper;
+import cn.iocoder.yudao.module.trade.service.brokerage.withdraw.BrokerageWithdrawServiceImpl;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link BrokerageWithdrawServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+@Import(BrokerageWithdrawServiceImpl.class)
+public class BrokerageWithdrawServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private BrokerageWithdrawServiceImpl brokerageWithdrawService;
+
+    @Resource
+    private BrokerageWithdrawMapper brokerageWithdrawMapper;
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetBrokerageWithdrawPage() {
+        // mock 数据
+        BrokerageWithdrawDO dbBrokerageWithdraw = randomPojo(BrokerageWithdrawDO.class, o -> { // 等会查询到
+            o.setUserId(null);
+            o.setType(null);
+            o.setName(null);
+            o.setAccountNo(null);
+            o.setBankName(null);
+            o.setStatus(null);
+            o.setCreateTime(null);
+        });
+        brokerageWithdrawMapper.insert(dbBrokerageWithdraw);
+        // 测试 userId 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setUserId(null)));
+        // 测试 type 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setType(null)));
+        // 测试 name 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setName(null)));
+        // 测试 accountNo 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAccountNo(null)));
+        // 测试 bankName 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setBankName(null)));
+        // 测试 status 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setStatus(null)));
+        // 测试 auditReason 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAuditReason(null)));
+        // 测试 auditTime 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setAuditTime(null)));
+        // 测试 remark 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setRemark(null)));
+        // 测试 createTime 不匹配
+        brokerageWithdrawMapper.insert(cloneIgnoreId(dbBrokerageWithdraw, o -> o.setCreateTime(null)));
+        // 准备参数
+        BrokerageWithdrawPageReqVO reqVO = new BrokerageWithdrawPageReqVO();
+        reqVO.setUserId(null);
+        reqVO.setType(null);
+        reqVO.setName(null);
+        reqVO.setAccountNo(null);
+        reqVO.setBankName(null);
+        reqVO.setStatus(null);
+        reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+        // 调用
+        PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(reqVO);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbBrokerageWithdraw, pageResult.getList().get(0));
+    }
+
+}

+ 1 - 0
yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql

@@ -4,3 +4,4 @@ DELETE FROM trade_after_sale;
 DELETE FROM trade_after_sale_log;
 DELETE FROM trade_brokerage_user;
 DELETE FROM trade_brokerage_record;
+DELETE FROM "trade_brokerage_withdraw";

+ 26 - 1
yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql

@@ -163,4 +163,29 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_record"
     "deleted"       bit      NOT NULL DEFAULT FALSE,
     "tenant_id"      bigint   not null default '0',
     PRIMARY KEY ("id")
-) COMMENT '佣金记录';
+) COMMENT '佣金记录';
+CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw"
+(
+    "id"                  int      NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "user_id"             bigint   NOT NULL,
+    "price"               int      NOT NULL,
+    "fee_price"           int      NOT NULL,
+    "total_price"         int      NOT NULL,
+    "type"                varchar  NOT NULL,
+    "name"                varchar,
+    "account_no"          varchar,
+    "bank_name"           varchar,
+    "bank_address"        varchar,
+    "account_qr_code_url" varchar,
+    "status"              varchar  NOT NULL,
+    "audit_reason"        varchar,
+    "audit_time"          varchar,
+    "remark"              varchar,
+    "creator"             varchar           DEFAULT '',
+    "create_time"         datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater"             varchar           DEFAULT '',
+    "update_time"         datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    "deleted"             bit      NOT NULL DEFAULT FALSE,
+    "tenant_id"      bigint   not null default '0',目
+    PRIMARY KEY ("id")
+) COMMENT '佣金提现';