Commit bce96b29a67044a6c6340054a9f5d73295c0ea93

Authored by puhui999
2 parents 42c47d9b 437185cb

Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product

# Conflicts:
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
Showing 188 changed files with 3212 additions and 961 deletions

Too many changes.

To preserve performance only 100 of 188 files are displayed.

sql/mysql/brokerage.sql
1 1 -- 增加配置表
2   -create table trade_config
  2 +CREATE TABLE trade_config
3 3 (
4   - id bigint auto_increment comment '自增主键' primary key,
5   - brokerage_enabled bit default 1 not null comment '是否启用分佣',
6   - brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:1-人人分销 2-指定分销',
7   - brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖',
8   - brokerage_post_urls varchar(2000) default '' null comment '分销海报图地址数组',
9   - brokerage_first_percent int default 0 not null comment '一级返佣比例',
10   - brokerage_second_percent int default 0 not null comment '二级返佣比例',
11   - brokerage_withdraw_min_price int default 0 not null comment '用户提现最低金额',
12   - brokerage_bank_names varchar(200) default '' not null comment '提现银行(字典类型=brokerage_bank_name)',
13   - brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)',
14   - brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝',
15   - creator varchar(64) default '' null comment '创建者',
16   - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
17   - updater varchar(64) default '' null comment '更新者',
18   - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
19   - deleted bit default b'0' not null comment '是否删除',
20   - tenant_id bigint default 0 not null comment '租户编号'
21   -) comment '交易中心配置';
  4 + id BIGINT AUTO_INCREMENT COMMENT '自增主键' PRIMARY KEY,
  5 + brokerage_enabled BIT DEFAULT 1 NOT NULL COMMENT '是否启用分佣',
  6 + brokerage_enabled_condition TINYINT DEFAULT 1 NOT NULL COMMENT '分佣模式:1-人人分销 2-指定分销',
  7 + brokerage_bind_mode TINYINT DEFAULT 1 NOT NULL COMMENT '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖',
  8 + brokerage_poster_urls VARCHAR(2000) DEFAULT '' NULL COMMENT '分销海报图地址数组',
  9 + brokerage_first_percent INT DEFAULT 0 NOT NULL COMMENT '一级返佣比例',
  10 + brokerage_second_percent INT DEFAULT 0 NOT NULL COMMENT '二级返佣比例',
  11 + brokerage_withdraw_min_price INT DEFAULT 0 NOT NULL COMMENT '用户提现最低金额',
  12 + brokerage_withdraw_fee_percent INT DEFAULT 0 NOT NULL COMMENT '提现手续费百分比',
  13 + brokerage_bank_names VARCHAR(200) DEFAULT '' NOT NULL COMMENT '提现银行(字典类型=brokerage_bank_name)',
  14 + brokerage_frozen_days INT DEFAULT 7 NOT NULL COMMENT '佣金冻结时间(天)',
  15 + brokerage_withdraw_types VARCHAR(32) DEFAULT '1,2,3,4' NOT NULL COMMENT '提现方式:1-钱包;2-银行卡;3-微信;4-支付宝',
  16 + creator VARCHAR(64) DEFAULT '' NULL COMMENT '创建者',
  17 + create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间',
  18 + updater VARCHAR(64) DEFAULT '' NULL COMMENT '更新者',
  19 + update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  20 + deleted BIT DEFAULT b'0' NOT NULL COMMENT '是否删除',
  21 + tenant_id BIGINT DEFAULT 0 NOT NULL COMMENT '租户编号'
  22 +) COMMENT '交易中心配置';
  23 +
  24 +# alter table trade_config
  25 +# add brokerage_withdraw_fee_percent int default 0 not null comment '提现手续费百分比' after brokerage_withdraw_min_price;
22 26  
23 27 # alter table trade_brokerage_user
24 28 # add level int not null default 1 comment '等级' after frozen_price;
... ... @@ -36,8 +40,6 @@ create table trade_brokerage_user
36 40 brokerage_time datetime null comment '成为分销员时间',
37 41 price int default 0 not null comment '可用佣金',
38 42 frozen_price int default 0 not null comment '冻结佣金',
39   - level int default 1 not null comment '等级',
40   - path varchar(2000) null comment '路径',
41 43 creator varchar(64) default '' null comment '创建者',
42 44 create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
43 45 updater varchar(64) default '' null comment '更新者',
... ... @@ -83,7 +85,7 @@ create index idx_status on trade_brokerage_record (status) comment '状态';
83 85  
84 86 create table trade_brokerage_withdraw
85 87 (
86   - id int auto_increment comment '编号'
  88 + id bigint auto_increment comment '编号'
87 89 primary key,
88 90 user_id bigint not null comment '用户编号',
89 91 price int default 0 not null comment '提现金额',
... ... @@ -137,7 +139,8 @@ insert into system_dict_type(type, name)
137 139 values ('brokerage_record_biz_type', '佣金记录业务类型');
138 140 insert into system_dict_data(dict_type, label, value, sort)
139 141 values ('brokerage_record_biz_type', '订单返佣', 1, 1),
140   - ('brokerage_record_biz_type', '申请提现', 2, 2);
  142 + ('brokerage_record_biz_type', '申请提现', 2, 2),
  143 + ('brokerage_record_biz_type', '申请提现驳回', 3, 3);
141 144  
142 145 insert into system_dict_type(type, name)
143 146 values ('brokerage_record_status', '佣金记录状态');
... ...
sql/mysql/pay_wallet.sql
... ... @@ -10,6 +10,7 @@ CREATE TABLE `pay_wallet`
10 10 `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分',
11 11 `total_expense` int NOT NULL DEFAULT 0 COMMENT '累计支出,单位分',
12 12 `total_recharge` int NOT NULL DEFAULT 0 COMMENT '累计充值,单位分',
  13 + `freeze_price` int NOT NULL DEFAULT 0 COMMENT '冻结金额,单位分',
13 14 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
14 15 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
15 16 `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
... ... @@ -50,18 +51,19 @@ CREATE TABLE `pay_wallet_recharge`
50 51 (
51 52 `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
52 53 `wallet_id` bigint NOT NULL COMMENT '会员钱包 id',
53   - `price` int NOT NULL COMMENT '用户实际到账余额,例如充 100 送 20,则该值是 120',
  54 + `total_price` int NOT NULL COMMENT '用户实际到账余额,例如充 100 送 20,则该值是 120',
54 55 `pay_price` int NOT NULL COMMENT '实际支付金额',
55   - `wallet_bonus` int NOT NULL COMMENT '钱包赠送金额',
  56 + `bonus_price` int NOT NULL COMMENT '钱包赠送金额',
56 57 `pay_status` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否已支付:[0:未支付 1:已经支付过]',
57 58 `pay_order_id` bigint NULL COMMENT '支付订单编号',
58 59 `pay_channel_code` varchar(16) NULL COMMENT '支付成功的支付渠道',
59 60 `pay_time` datetime NULL COMMENT '订单支付时间',
60 61 `pay_refund_id` bigint NULL COMMENT '支付退款单编号',
61   - `refund_price` int NOT NULL DEFAULT 0 COMMENT '退款金额,包含赠送金额',
  62 + `refund_total_price` int NOT NULL DEFAULT 0 COMMENT '退款金额,包含赠送金额',
62 63 `refund_pay_price` int NOT NULL DEFAULT 0 COMMENT '退款支付金额',
63   - `refund_wallet_bonus` int NOT NULL DEFAULT 0 COMMENT '退款钱包赠送金额',
  64 + `refund_bonus_price` int NOT NULL DEFAULT 0 COMMENT '退款钱包赠送金额',
64 65 `refund_time` datetime NULL COMMENT '退款时间',
  66 + `refund_status` int NOT NULL DEFAULT 0 COMMENT '退款状态',
65 67 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
66 68 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
67 69 `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
... ...
sql/mysql/point.sql 0 → 100644
  1 +ALTER TABLE trade_order ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price;
  2 +ALTER TABLE trade_order ADD COLUMN refund_point int NOT NULL DEFAULT 0 COMMENT '退还的使用积分' AFTER use_point;
  3 +ALTER TABLE trade_order ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER refund_point;
  4 +
  5 +ALTER TABLE trade_order_item ADD COLUMN use_point int NOT NULL DEFAULT 0 COMMENT '使用的积分' AFTER point_price;
  6 +ALTER TABLE trade_order_item ADD COLUMN give_point int NOT NULL DEFAULT 0 COMMENT '赠送的积分' AFTER use_point;
... ...
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java
1 1 package cn.iocoder.yudao.framework.common.util.number;
2 2  
  3 +import cn.hutool.core.math.Money;
3 4 import cn.hutool.core.util.NumberUtil;
4 5  
5 6 import java.math.BigDecimal;
... ... @@ -16,7 +17,7 @@ public class MoneyUtils {
16 17 * 计算百分比金额,四舍五入
17 18 *
18 19 * @param price 金额
19   - * @param rate 百分比,例如说 56.77% 则传入 56.77
  20 + * @param rate 百分比,例如说 56.77% 则传入 56.77
20 21 * @return 百分比金额
21 22 */
22 23 public static Integer calculateRatePrice(Integer price, Double rate) {
... ... @@ -27,24 +28,46 @@ public class MoneyUtils {
27 28 * 计算百分比金额,向下传入
28 29 *
29 30 * @param price 金额
30   - * @param rate 百分比,例如说 56.77% 则传入 56.77
  31 + * @param rate 百分比,例如说 56.77% 则传入 56.77
31 32 * @return 百分比金额
32 33 */
33 34 public static Integer calculateRatePriceFloor(Integer price, Double rate) {
34 35 return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue();
35 36 }
36 37  
37   - /**
38   - * 计算百分比金额
39   - *
40   - * @param price 金额
41   - * @param rate 百分比,例如说 56.77% 则传入 56.77
42   - * @param scale 保留小数位数
43   - * @param roundingMode 舍入模式
44   - */
45   - public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
46   - return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
47   - .divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
48   - }
  38 + /**
  39 + * 计算百分比金额
  40 + *
  41 + * @param price 金额
  42 + * @param rate 百分比,例如说 56.77% 则传入 56.77
  43 + * @param scale 保留小数位数
  44 + * @param roundingMode 舍入模式
  45 + */
  46 + public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
  47 + return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
  48 + .divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
  49 + }
  50 +
  51 + /**
  52 + * 分转元
  53 + *
  54 + * @param fen 分
  55 + * @return 元
  56 + */
  57 + public static BigDecimal fenToYuan(int fen) {
  58 + return new Money(0, fen).getAmount();
  59 + }
  60 +
  61 + /**
  62 + * 分转元(字符串)
  63 + *
  64 + * 例如说 fen 为 1 时,则结果为 0.01
  65 + *
  66 + * @param fen 分
  67 + * @return 元
  68 + */
  69 + public static String fenToYuanStr(int fen) {
  70 + return new Money(0, fen).toString();
  71 + }
49 72  
50 73 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml
... ... @@ -14,7 +14,7 @@
14 14 <name>${project.artifactId}</name>
15 15 <description>
16 16 错误码 ErrorCode 的自动配置功能,提供如下功能:
17   - 1. 远程读取:项目启动时,从 system-server 服务,读取数据库中的 ErrorCode 错误码,实现错误码的提水可配置;
  17 + 1. 远程读取:项目启动时,从 system-server 服务,读取数据库中的 ErrorCode 错误码,实现错误码的提示可配置;
18 18 2. 自动更新:管理员在管理后台修数据库中的 ErrorCode 错误码时,项目自动从 system-server 服务加载最新的 ErrorCode 错误码;
19 19 3. 自动写入:项目启动时,将项目本地的错误码写到 system-server 服务中,方便管理员在管理后台编辑;
20 20 </description>
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
... ... @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  7 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 9  
8 10 import java.util.Map;
9 11  
... ... @@ -76,4 +78,12 @@ public interface PayClient {
76 78 */
77 79 PayRefundRespDTO getRefund(String outTradeNo, String outRefundNo);
78 80  
  81 + /**
  82 + * 调用渠道,进行转账
  83 + *
  84 + * @param reqDTO 统一转账请求信息
  85 + * @return 转账信息
  86 + */
  87 + PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO);
  88 +
79 89 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.client.dto.transfer;
  2 +
  3 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferStatusRespEnum;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +/**
  9 + * 统一转账 Response DTO
  10 + *
  11 + * @author jason
  12 + */
  13 +@Data
  14 +public class PayTransferRespDTO {
  15 +
  16 + /**
  17 + * 转账状态
  18 + *
  19 + * 关联 {@link PayTransferStatusRespEnum#getStatus()}
  20 + */
  21 + private Integer status;
  22 +
  23 + /**
  24 + * 外部转账单号
  25 + *
  26 + */
  27 + private String outTransferNo;
  28 +
  29 + /**
  30 + * 支付渠道编号
  31 + */
  32 + private String channelOrderNo;
  33 +
  34 + /**
  35 + * 支付成功时间
  36 + */
  37 + private LocalDateTime successTime;
  38 +
  39 + /**
  40 + * 原始的返回结果
  41 + */
  42 + private Object rawData;
  43 +
  44 + /**
  45 + * 调用渠道的错误码
  46 + */
  47 + private String channelErrorCode;
  48 + /**
  49 + * 调用渠道报错时,错误信息
  50 + */
  51 + private String channelErrorMsg;
  52 +
  53 + /**
  54 + * 创建【WAITING】状态的转账返回
  55 + */
  56 + public static PayTransferRespDTO waitingOf(String channelOrderNo,
  57 + String outTransferNo, Object rawData) {
  58 + PayTransferRespDTO respDTO = new PayTransferRespDTO();
  59 + respDTO.status = PayTransferStatusRespEnum.WAITING.getStatus();
  60 + respDTO.channelOrderNo = channelOrderNo;
  61 + respDTO.outTransferNo = outTransferNo;
  62 + respDTO.rawData = rawData;
  63 + return respDTO;
  64 + }
  65 +
  66 + /**
  67 + * 创建【FAILURE】状态的转账返回
  68 + */
  69 + public static PayTransferRespDTO failureOf(String channelErrorCode, String channelErrorMsg,
  70 + String outTransferNo, Object rawData) {
  71 + PayTransferRespDTO respDTO = new PayTransferRespDTO();
  72 + respDTO.status = PayTransferStatusRespEnum.FAILURE.getStatus();
  73 + respDTO.channelErrorCode = channelErrorCode;
  74 + respDTO.channelErrorMsg = channelErrorMsg;
  75 + // 相对通用的字段
  76 + respDTO.outTransferNo = outTransferNo;
  77 + respDTO.rawData = rawData;
  78 + return respDTO;
  79 + }
  80 +
  81 + /**
  82 + * 创建【SUCCESS】状态的转账返回
  83 + */
  84 + public static PayTransferRespDTO successOf(String channelTransferNo, LocalDateTime successTime,
  85 + String outTransferNo, Object rawData) {
  86 + PayTransferRespDTO respDTO = new PayTransferRespDTO();
  87 + respDTO.status = PayTransferStatusRespEnum.SUCCESS.getStatus();
  88 + respDTO.channelOrderNo = channelTransferNo;
  89 + respDTO.successTime = successTime;
  90 + // 相对通用的字段
  91 + respDTO.outTransferNo = outTransferNo;
  92 + respDTO.rawData = rawData;
  93 + return respDTO;
  94 + }
  95 +
  96 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.client.dto.transfer;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
  5 +import lombok.Data;
  6 +import org.hibernate.validator.constraints.Length;
  7 +
  8 +import javax.validation.constraints.Min;
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.util.Map;
  12 +
  13 +/**
  14 + * 统一转账 Request DTO
  15 + *
  16 + * @author jason
  17 + */
  18 +@Data
  19 +public class PayTransferUnifiedReqDTO {
  20 +
  21 + /**
  22 + * 转账类型
  23 + *
  24 + * 关联 {@link PayTransferTypeEnum#getType()}
  25 + */
  26 + @NotNull(message = "转账类型不能为空")
  27 + @InEnum(PayTransferTypeEnum.class)
  28 + private Integer type;
  29 +
  30 + /**
  31 + * 用户 IP
  32 + */
  33 + @NotEmpty(message = "用户 IP 不能为空")
  34 + private String userIp;
  35 +
  36 + @NotEmpty(message = "外部转账单编号不能为空")
  37 + private String outTransferNo;
  38 +
  39 + /**
  40 + * 转账金额,单位:分
  41 + */
  42 + @NotNull(message = "转账金额不能为空")
  43 + @Min(value = 1, message = "转账金额必须大于零")
  44 + private Integer price;
  45 +
  46 + /**
  47 + * 转账标题
  48 + */
  49 + @NotEmpty(message = "转账标题不能为空")
  50 + @Length(max = 128, message = "转账标题不能超过 128")
  51 + private String title;
  52 +
  53 + /**
  54 + * 收款方信息,转账类型不同,收款方信息不同
  55 + */
  56 + @NotEmpty(message = "收款方信息 不能为空")
  57 + private Map<String, String> payeeInfo;
  58 +
  59 + /**
  60 + * 支付渠道的额外参数
  61 + *
  62 + */
  63 + private Map<String, String> channelExtras;
  64 +
  65 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
... ... @@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
8 8 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
9 9 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
10 10 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  11 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  12 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
11 13 import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
12 14 import lombok.extern.slf4j.Slf4j;
13 15  
... ... @@ -181,6 +183,26 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
181 183 protected abstract PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo)
182 184 throws Throwable;
183 185  
  186 + @Override
  187 + public final PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  188 + ValidationUtils.validate(reqDTO);
  189 + PayTransferRespDTO resp;
  190 + try{
  191 + resp = doUnifiedTransfer(reqDTO);
  192 + }catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
  193 + throw ex;
  194 + } catch (Throwable ex) {
  195 + // 系统异常,则包装成 PayException 异常抛出
  196 + log.error("[unifiedTransfer][客户端({}) request({}) 发起转账异常]",
  197 + getId(), toJsonString(reqDTO), ex);
  198 + throw buildPayException(ex);
  199 + }
  200 + return resp;
  201 + }
  202 +
  203 + protected abstract PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO)
  204 + throws Throwable;
  205 +
184 206 // ========== 各种工具方法 ==========
185 207  
186 208 private PayException buildPayException(Throwable ex) {
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
... ... @@ -50,6 +50,8 @@ public class PayClientFactoryImpl implements PayClientFactory {
50 50 clientClass.put(ALIPAY_APP, AlipayAppPayClient.class);
51 51 clientClass.put(ALIPAY_PC, AlipayPcPayClient.class);
52 52 clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class);
  53 + // 支付包转账客户端
  54 + clientClass.put(ALIPAY_TRANSFER, AlipayTransferClient.class);
53 55 // Mock 支付客户端
54 56 clientClass.put(MOCK, MockPayClient.class);
55 57 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
... ... @@ -150,6 +150,10 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
150 150 // 2.1 执行请求
151 151 AlipayTradeRefundResponse response = client.execute(request);
152 152 if (!response.isSuccess()) {
  153 + // 当出现 ACQ.SYSTEM_ERROR, 退款可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
  154 + if (ObjectUtils.equalsAny(response.getSubCode(), "ACQ.SYSTEM_ERROR", "SYSTEM_ERROR")) {
  155 + return PayRefundRespDTO.waitingOf(null, reqDTO.getOutRefundNo(), response);
  156 + }
153 157 return PayRefundRespDTO.failureOf(response.getSubCode(), response.getSubMsg(), reqDTO.getOutRefundNo(), response);
154 158 }
155 159 // 2.2 创建返回结果
... ... @@ -198,6 +202,8 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
198 202 return PayRefundRespDTO.waitingOf(null, outRefundNo, response);
199 203 }
200 204  
  205 +
  206 +
201 207 // ========== 各种工具方法 ==========
202 208  
203 209 protected String formatAmount(Integer amount) {
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java
... ... @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  5 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  6 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
5 7 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
6 8 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
7 9 import com.alipay.api.AlipayApiException;
... ... @@ -57,4 +59,8 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient {
57 59 reqDTO.getOutTradeNo(), response);
58 60 }
59 61  
  62 + @Override
  63 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  64 + throw new UnsupportedOperationException("支付宝【App 支付】不支持转账操作");
  65 + }
60 66 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java
... ... @@ -5,6 +5,8 @@ import cn.hutool.core.map.MapUtil;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
7 7 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  9 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
8 10 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
9 11 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
10 12 import com.alipay.api.AlipayApiException;
... ... @@ -75,4 +77,8 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient {
75 77 reqDTO.getOutTradeNo(), response);
76 78 }
77 79  
  80 + @Override
  81 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  82 + throw new UnsupportedOperationException("支付宝【条码支付】不支持转账操作");
  83 + }
78 84 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java
... ... @@ -4,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.http.Method;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  7 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 9 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
8 10 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
9 11 import com.alipay.api.AlipayApiException;
... ... @@ -67,4 +69,8 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient {
67 69 reqDTO.getOutTradeNo(), response);
68 70 }
69 71  
  72 + @Override
  73 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  74 + throw new UnsupportedOperationException("支付宝【PC 网站】不支持转账操作");
  75 + }
70 76 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
... ... @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2  
3 3 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  5 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  6 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
5 7 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
6 8 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
7 9 import com.alipay.api.AlipayApiException;
... ... @@ -54,4 +56,8 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient {
54 56 reqDTO.getOutTradeNo(), response);
55 57 }
56 58  
  59 + @Override
  60 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  61 + throw new UnsupportedOperationException("支付宝【扫码支付】不支持转账操作");
  62 + }
57 63 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayTransferClient.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  6 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  7 +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  9 +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
  10 +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  11 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  12 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
  13 +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
  14 +import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
  15 +import com.alipay.api.AlipayApiException;
  16 +import com.alipay.api.domain.AlipayFundTransUniTransferModel;
  17 +import com.alipay.api.domain.Participant;
  18 +import com.alipay.api.request.AlipayFundTransUniTransferRequest;
  19 +import com.alipay.api.response.AlipayFundTransUniTransferResponse;
  20 +import lombok.extern.slf4j.Slf4j;
  21 +
  22 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
  23 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
  24 +
  25 +/**
  26 + * 支付宝转账的 PayClient 实现类
  27 + *
  28 + * @author jason
  29 + */
  30 +@Slf4j
  31 +public class AlipayTransferClient extends AbstractAlipayPayClient {
  32 + public AlipayTransferClient(Long channelId, AlipayPayClientConfig config) {
  33 + super(channelId, PayChannelEnum.ALIPAY_TRANSFER.getCode(), config);
  34 + }
  35 + @Override
  36 + protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
  37 + throw new UnsupportedOperationException("支付宝转账不支持统一下单请求");
  38 + }
  39 + @Override
  40 + protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
  41 + throw new UnsupportedOperationException("支付宝转账不支持统一退款请求");
  42 + }
  43 + @Override
  44 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) throws AlipayApiException {
  45 + // 1.1 构建 AlipayFundTransUniTransferModel
  46 + AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
  47 + // ① 通用的参数
  48 + model.setTransAmount(formatAmount(reqDTO.getPrice())); // 转账金额
  49 + model.setOrderTitle(reqDTO.getTitle()); // 转账业务的标题,用于在支付宝用户的账单里显示。
  50 + model.setOutBizNo(reqDTO.getOutTransferNo());
  51 + model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
  52 + model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。
  53 + model.setBusinessParams(JsonUtils.toJsonString(reqDTO.getChannelExtras()));
  54 + PayTransferTypeEnum transferType = PayTransferTypeEnum.valueOf(reqDTO.getType());
  55 + switch(transferType){
  56 + case WX_BALANCE :
  57 + case WALLET_BALANCE : {
  58 + log.error("[doUnifiedTransfer],支付宝转账不支持的转账类型{}", transferType);
  59 + throw new UnsupportedOperationException(String.format("支付宝转账不支持转账类型: %s",transferType.getName()));
  60 + }
  61 + case ALIPAY_BALANCE : {
  62 + // ② 个性化的参数
  63 + Participant payeeInfo = new Participant();
  64 + payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
  65 + String logonId = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_LOGON_ID");
  66 + if (StrUtil.isEmpty(logonId)) {
  67 + throw exception0(BAD_REQUEST.getCode(), "支付包登录 ID 不能为空");
  68 + }
  69 + String accountName = MapUtil.getStr(reqDTO.getPayeeInfo(), "ALIPAY_ACCOUNT_NAME");
  70 + if (StrUtil.isEmpty(accountName)) {
  71 + throw exception0(BAD_REQUEST.getCode(), "支付包账户名称不能为空");
  72 + }
  73 + payeeInfo.setIdentity(logonId); // 支付宝登录号
  74 + payeeInfo.setName(accountName); // 支付宝账号姓名
  75 + model.setPayeeInfo(payeeInfo);
  76 + // 1.2 构建 AlipayFundTransUniTransferRequest
  77 + AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
  78 + request.setBizModel(model);
  79 + // 执行请求
  80 + AlipayFundTransUniTransferResponse response = client.certificateExecute(request);
  81 + // 处理结果
  82 + if (!response.isSuccess()) {
  83 + // 当出现 SYSTEM_ERROR, 转账可能成功也可能失败。 返回 WAIT 状态. 后续 job 会轮询
  84 + if (ObjectUtils.equalsAny(response.getSubCode(), "SYSTEM_ERROR", "ACQ.SYSTEM_ERROR")) {
  85 + return PayTransferRespDTO.waitingOf(null, reqDTO.getOutTransferNo(), response);
  86 + }
  87 + return PayTransferRespDTO.failureOf(response.getSubCode(), response.getSubMsg(),
  88 + reqDTO.getOutTransferNo(), response);
  89 + }
  90 + return PayTransferRespDTO.successOf(response.getOrderId(), parseTime(response.getTransDate()),
  91 + response.getOutBizNo(), response);
  92 + }
  93 + case BANK_CARD : {
  94 + Participant payeeInfo = new Participant();
  95 + payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
  96 + throw new UnsupportedOperationException("待实现");
  97 + }
  98 + default: {
  99 + throw new IllegalStateException("不正确的转账类型: " + transferType);
  100 + }
  101 + }
  102 + }
  103 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
... ... @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
3 3 import cn.hutool.http.Method;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
  6 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  7 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
6 8 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
7 9 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
8 10 import com.alipay.api.AlipayApiException;
... ... @@ -56,4 +58,8 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient {
56 58 reqDTO.getOutTradeNo(), response);
57 59 }
58 60  
  61 + @Override
  62 + public PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  63 + throw new UnsupportedOperationException("支付宝【Wap 网站】不支持转账操作");
  64 + }
59 65 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java
... ... @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
4 4 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
5 5 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
6 6 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  7 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
7 9 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
8 10 import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
9 11 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
... ... @@ -64,4 +66,8 @@ public class MockPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
64 66 throw new UnsupportedOperationException("模拟支付无支付回调");
65 67 }
66 68  
  69 + @Override
  70 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  71 + throw new UnsupportedOperationException("待实现");
  72 + }
67 73 }
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
... ... @@ -12,6 +12,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
12 12 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
13 13 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
14 14 import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
  15 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  16 +import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
15 17 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
16 18 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
17 19 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
... ... @@ -425,6 +427,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
425 427 }
426 428 }
427 429  
  430 + @Override
  431 + protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
  432 + throw new UnsupportedOperationException("待实现");
  433 + }
428 434 // ========== 各种工具方法 ==========
429 435  
430 436 static String formatDateV2(LocalDateTime time) {
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java
... ... @@ -28,6 +28,7 @@ public enum PayChannelEnum {
28 28 ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class),
29 29 ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class),
30 30 ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class),
  31 + ALIPAY_TRANSFER("alipay_transfer", "支付宝转账", AlipayPayClientConfig.class),
31 32  
32 33 MOCK("mock", "模拟支付", NonePayClientConfig.class),
33 34  
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferStatusRespEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.enums.transfer;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 渠道的转账状态枚举
  8 + *
  9 + * @author jason
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum PayTransferStatusRespEnum {
  14 +
  15 + WAITING(0, "等待转账"),
  16 + SUCCESS(10, "转账成功"),
  17 + FAILURE(20, "转账失败");
  18 +
  19 + private final Integer status;
  20 + private final String name;
  21 +}
... ...
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.enums.transfer;
  2 +
  3 +import cn.hutool.core.util.ArrayUtil;
  4 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Getter;
  7 +
  8 +import java.util.Arrays;
  9 +
  10 +/**
  11 + * 转账类型枚举
  12 + *
  13 + * @author jason
  14 + */
  15 +@AllArgsConstructor
  16 +@Getter
  17 +public enum PayTransferTypeEnum implements IntArrayValuable {
  18 + ALIPAY_BALANCE(1, "支付宝余额"),
  19 + WX_BALANCE(2, "微信余额"),
  20 + BANK_CARD(3, "银行卡"),
  21 + WALLET_BALANCE(4, "钱包余额");
  22 +
  23 + private final Integer type;
  24 + private final String name;
  25 +
  26 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PayTransferTypeEnum::getType).toArray();
  27 +
  28 + @Override
  29 + public int[] array() {
  30 + return ARRAYS;
  31 + }
  32 +
  33 + public static PayTransferTypeEnum valueOf(Integer type) {
  34 + return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
  35 + }
  36 +}
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java
... ... @@ -100,14 +100,6 @@ public class LambdaQueryWrapperX&lt;T&gt; extends LambdaQueryWrapper&lt;T&gt; {
100 100 return betweenIfPresent(column, val1, val2);
101 101 }
102 102  
103   - // TODO @疯狂:这个是 mysql 独有的,不好做成通用的哈。如果多层级,有没可能先查询一个层级,再查询一个层级;形成 set 后,直接去 in?
104   - public LambdaQueryWrapperX<T> findInSetIfPresent(SFunction<T, ?> column, Object val) {
105   - if (val != null) {
106   - return (LambdaQueryWrapperX<T>) super.apply("FIND_IN_SET({0}, " + columnToString(column) + ")", val);
107   - }
108   - return this;
109   - }
110   -
111 103 // ========== 重写父类方法,方便链式调用 ==========
112 104  
113 105 @Override
... ...
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.jackson.config;
2 2  
3   -import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
  3 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 4 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
5 5 import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
6   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  6 +import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer;
7 7 import com.fasterxml.jackson.databind.ObjectMapper;
8 8 import com.fasterxml.jackson.databind.module.SimpleModule;
  9 +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
  10 +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
  11 +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
  12 +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
9 13 import lombok.extern.slf4j.Slf4j;
10 14 import org.springframework.beans.BeansException;
11 15 import org.springframework.beans.factory.config.BeanPostProcessor;
12 16 import org.springframework.boot.autoconfigure.AutoConfiguration;
13 17 import org.springframework.context.annotation.Bean;
14 18  
  19 +import java.time.LocalDate;
15 20 import java.time.LocalDateTime;
  21 +import java.time.LocalTime;
16 22  
17 23 @AutoConfiguration
18 24 @Slf4j
... ... @@ -36,6 +42,10 @@ public class YudaoJacksonAutoConfiguration {
36 42 simpleModule
37 43 .addSerializer(Long.class, NumberSerializer.INSTANCE)
38 44 .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
  45 + .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
  46 + .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
  47 + .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
  48 + .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
39 49 .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE)
40 50 .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
41 51  
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
... ... @@ -39,7 +39,7 @@ public interface ProductSkuApi {
39 39 List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds);
40 40  
41 41 /**
42   - * 更新 SKU 库存
  42 + * 更新 SKU 库存(增加 or 减少)
43 43 *
44 44 * @param updateStockReqDTO 更新请求
45 45 */
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
... ... @@ -111,6 +111,11 @@ public class ProductSpuRespDTO {
111 111 // ========== 物流相关字段 =========
112 112  
113 113 /**
  114 + * 赠送积分
  115 + */
  116 + private Integer giveIntegral;
  117 +
  118 + /**
114 119 * 物流配置模板编号
115 120 *
116 121 * 对应 TradeDeliveryExpressTemplateDO 的 id 编号
... ... @@ -132,4 +137,15 @@ public class ProductSpuRespDTO {
132 137 */
133 138 private Integer clickCount;
134 139  
  140 +
  141 + // ========== 分销相关字段 =========
  142 +
  143 + /**
  144 + * 分销类型
  145 + *
  146 + * false - 默认
  147 + * true - 自行设置
  148 + */
  149 + private Boolean subCommissionType;
  150 +
135 151 }
... ...
yudao-module-mall/yudao-module-product-biz/pom.xml
... ... @@ -23,12 +23,6 @@
23 23 <artifactId>yudao-module-product-api</artifactId>
24 24 <version>${revision}</version>
25 25 </dependency>
26   - <!-- TODO 芋艿:看看~~~ -->
27   - <dependency>
28   - <groupId>cn.iocoder.boot</groupId>
29   - <artifactId>yudao-module-trade-api</artifactId>
30   - <version>${revision}</version>
31   - </dependency>
32 26 <dependency>
33 27 <groupId>cn.iocoder.boot</groupId>
34 28 <artifactId>yudao-module-member-api</artifactId>
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
1 1 package cn.iocoder.yudao.module.product.api.property;
2 2  
3 3 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
4   -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
  4 +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
5 5 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
6 6 import org.springframework.stereotype.Service;
7 7 import org.springframework.validation.annotation.Validated;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property;
2 2  
3   -import cn.hutool.core.collection.CollectionUtil;
4   -import cn.hutool.crypto.symmetric.AES;
5 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
8 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
9 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
10 8 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
11   -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
  9 +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
12 10 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
13 11 import io.swagger.v3.oas.annotations.Operation;
14 12 import io.swagger.v3.oas.annotations.Parameter;
... ... @@ -20,9 +18,6 @@ import org.springframework.web.bind.annotation.*;
20 18 import javax.annotation.Resource;
21 19 import javax.validation.Valid;
22 20  
23   -import java.util.Arrays;
24   -import java.util.List;
25   -
26 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
27 22  
28 23 @Tag(name = "管理后台 - 商品属性值")
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
1 1 package cn.iocoder.yudao.module.product.controller.app.spu;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
  7 +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
  8 +import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
  9 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
6   -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
7 11 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
  12 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
8 13 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
9 14 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
10 15 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
... ... @@ -23,10 +28,12 @@ import org.springframework.web.bind.annotation.RestController;
23 28  
24 29 import javax.annotation.Resource;
25 30 import javax.validation.Valid;
  31 +import java.util.Collections;
26 32 import java.util.List;
27 33  
28 34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
29 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  36 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
30 37 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
31 38 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
32 39  
... ... @@ -41,6 +48,11 @@ public class AppProductSpuController {
41 48 @Resource
42 49 private ProductSkuService productSkuService;
43 50  
  51 + @Resource
  52 + private MemberLevelApi memberLevelApi;
  53 + @Resource
  54 + private MemberUserApi memberUserApi;
  55 +
44 56 @GetMapping("/list")
45 57 @Operation(summary = "获得商品 SPU 列表")
46 58 @Parameters({
... ... @@ -51,14 +63,32 @@ public class AppProductSpuController {
51 63 @RequestParam("recommendType") String recommendType,
52 64 @RequestParam(value = "count", defaultValue = "10") Integer count) {
53 65 List<ProductSpuDO> list = productSpuService.getSpuList(recommendType, count);
54   - return success(ProductSpuConvert.INSTANCE.convertListForGetSpuList(list));
  66 + if (CollUtil.isEmpty(list)) {
  67 + return success(Collections.emptyList());
  68 + }
  69 +
  70 + // 拼接返回
  71 + List<AppProductSpuPageRespVO> voList = ProductSpuConvert.INSTANCE.convertListForGetSpuList(list);
  72 + // 处理 vip 价格
  73 + MemberLevelRespDTO memberLevel = getMemberLevel();
  74 + voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
  75 + return success(voList);
55 76 }
56 77  
57 78 @GetMapping("/page")
58 79 @Operation(summary = "获得商品 SPU 分页")
59 80 public CommonResult<PageResult<AppProductSpuPageRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
60 81 PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO);
61   - return success(ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult));
  82 + if (CollUtil.isEmpty(pageResult.getList())) {
  83 + return success(PageResult.empty(pageResult.getTotal()));
  84 + }
  85 +
  86 + // 拼接返回
  87 + PageResult<AppProductSpuPageRespVO> voPageResult = ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult);
  88 + // 处理 vip 价格
  89 + MemberLevelRespDTO memberLevel = getMemberLevel();
  90 + voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
  91 + return success(voPageResult);
62 92 }
63 93  
64 94 @GetMapping("/get-detail")
... ... @@ -74,10 +104,40 @@ public class AppProductSpuController {
74 104 throw exception(SPU_NOT_ENABLE);
75 105 }
76 106  
77   - // 查询商品 SKU
  107 + // 拼接返回
78 108 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
79   - // 拼接
80   - return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus));
  109 + AppProductSpuDetailRespVO detailVO = ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus);
  110 + // 处理 vip 价格
  111 + MemberLevelRespDTO memberLevel = getMemberLevel();
  112 + detailVO.setVipPrice(calculateVipPrice(detailVO.getPrice(), memberLevel));
  113 + return success(detailVO);
  114 + }
  115 +
  116 + private MemberLevelRespDTO getMemberLevel() {
  117 + Long userId = getLoginUserId();
  118 + if (userId == null) {
  119 + return null;
  120 + }
  121 + MemberUserRespDTO user = memberUserApi.getUser(userId);
  122 + if (user.getLevelId() == null || user.getLevelId() <= 0) {
  123 + return null;
  124 + }
  125 + return memberLevelApi.getMemberLevel(user.getLevelId());
  126 + }
  127 +
  128 + /**
  129 + * 计算会员 VIP 优惠价格
  130 + *
  131 + * @param price 原价
  132 + * @param memberLevel 会员等级
  133 + * @return 优惠价格
  134 + */
  135 + public Integer calculateVipPrice(Integer price, MemberLevelRespDTO memberLevel) {
  136 + if (memberLevel == null || memberLevel.getDiscountPercent() == null) {
  137 + return 0;
  138 + }
  139 + Integer newPrice = price * memberLevel.getDiscountPercent() / 100;
  140 + return price - newPrice;
81 141 }
82 142  
83 143 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java renamed to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyValueConvert.java
1   -package cn.iocoder.yudao.module.product.convert.propertyvalue;
  1 +package cn.iocoder.yudao.module.product.convert.property;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
... ... @@ -79,8 +79,6 @@ public interface ProductSpuConvert {
79 79 ProductSpuDO spu = list.get(i);
80 80 AppProductSpuPageRespVO spuVO = voList.get(i);
81 81 spuVO.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
82   - // 计算 vip 价格 TODO 芋艿:临时的逻辑,等 vip 支持后
83   - spuVO.setVipPrice((int) (spuVO.getPrice() * 0.9));
84 82 }
85 83 return voList;
86 84 }
... ... @@ -95,11 +93,6 @@ public interface ProductSpuConvert {
95 93 .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
96 94 // 处理 SKU
97 95 spuVO.setSkus(convertListForGetSpuDetail(skus));
98   - // 计算 vip 价格 TODO 芋艿:临时的逻辑,等 vip 支持后
99   - if (true) {
100   - spuVO.setVipPrice((int) (spuVO.getPrice() * 0.9));
101   - spuVO.getSkus().forEach(sku -> sku.setVipPrice((int) (sku.getPrice() * 0.9)));
102   - }
103 96 return spuVO;
104 97 }
105 98  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java
... ... @@ -179,6 +179,7 @@ public class ProductSpuDO extends BaseDO {
179 179 @TableField(typeHandler = JacksonTypeHandler.class)
180 180 private List<Long> giveCouponTemplateIds;
181 181  
  182 + // TODO @puhui999:字段估计要改成 brokerageType
182 183 /**
183 184 * 分销类型
184 185 *
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
1 1 /**
2   - * trade 模块,主要实现交易相关功能
  2 + * product 模块,主要实现交易相关功能
3 3 * 例如:订单、退款、购物车等功能。
4 4 *
5 5 * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
... ... @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
6 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
7 7 import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
8   -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
  8 +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
9 9 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
10 10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
11 11 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java
... ... @@ -11,7 +11,7 @@ public interface BargainActivityApi {
11 11 * 更新砍价活动库存
12 12 *
13 13 * @param id 砍价活动编号
14   - * @param count 购买数量
  14 + * @param count 购买数量
15 15 */
16 16 void updateBargainActivityStock(Long id, Integer count);
17 17  
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
... ... @@ -56,7 +56,6 @@ public interface ErrorCodeConstants {
56 56 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
57 57 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
58 58 ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
59   - ErrorCode SECKILL_ACTIVITY_APP_STATUS_CLOSED = new ErrorCode(1013008007, "秒杀活动已关闭");
60 59  
61 60 // ========== 秒杀时段 1013009000 ==========
62 61 ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
... ... @@ -69,7 +68,6 @@ public interface ErrorCodeConstants {
69 68 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
70 69 ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
71 70 ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
72   - ErrorCode COMBINATION_ACTIVITY_APP_STATUS_DISABLE = new ErrorCode(1013010005, "拼团活动已关闭");
73 71  
74 72 // ========== 拼团记录 1013011000 ==========
75 73 ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java
... ... @@ -22,8 +22,9 @@ public enum PromotionTypeEnum implements IntArrayValuable {
22 22 DISCOUNT_ACTIVITY(4, "限时折扣"),
23 23 REWARD_ACTIVITY(5, "满减送"),
24 24  
25   - MEMBER(6, "会员折扣"),
26   - COUPON(7, "优惠劵")
  25 + MEMBER_LEVEL(6, "会员折扣"),
  26 + COUPON(7, "优惠劵"),
  27 + POINT(8, "积分")
27 28 ;
28 29  
29 30 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionTypeEnum::getType).toArray();
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java
... ... @@ -24,14 +24,12 @@ import org.springframework.web.bind.annotation.RequestParam;
24 24 import org.springframework.web.bind.annotation.RestController;
25 25  
26 26 import javax.annotation.Resource;
27   -import java.util.Arrays;
  27 +import java.util.Collections;
28 28 import java.util.List;
29 29  
30 30 import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
31   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
32 31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
33 32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
34   -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_ACTIVITY_APP_STATUS_DISABLE;
35 33  
36 34 @Tag(name = "用户 APP - 拼团活动")
37 35 @RestController
... ... @@ -44,7 +42,7 @@ public class AppCombinationActivityController {
44 42 @Resource
45 43 private ProductSpuApi spuApi;
46 44  
47   -
  45 + // TODO 芋艿:增加 Spring Cache
48 46 @GetMapping("/list")
49 47 @Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
50 48 @Parameter(name = "count", description = "需要展示的数量", example = "6")
... ... @@ -52,11 +50,10 @@ public class AppCombinationActivityController {
52 50 @RequestParam(name = "count", defaultValue = "6") Integer count) {
53 51 List<CombinationActivityDO> list = activityService.getCombinationActivityListByCount(defaultIfNull(count, 6));
54 52 if (CollUtil.isEmpty(list)) {
55   - return success(CombinationActivityConvert.INSTANCE.convertAppList(list));
  53 + return success(Collections.emptyList());
56 54 }
57   -
  55 + // 拼接返回
58 56 List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(list, CombinationActivityDO::getSpuId));
59   - // TODO 芋艿:增加 Spring Cache
60 57 return success(CombinationActivityConvert.INSTANCE.convertAppList(list, spuList));
61 58 }
62 59  
... ... @@ -67,7 +64,7 @@ public class AppCombinationActivityController {
67 64 if (CollUtil.isEmpty(result.getList())) {
68 65 return success(PageResult.empty(result.getTotal()));
69 66 }
70   -
  67 + // 拼接返回
71 68 List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(result.getList(), CombinationActivityDO::getSpuId));
72 69 return success(CombinationActivityConvert.INSTANCE.convertAppPage(result, spuList));
73 70 }
... ... @@ -78,15 +75,12 @@ public class AppCombinationActivityController {
78 75 public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) {
79 76 // 1、获取活动
80 77 CombinationActivityDO combinationActivity = activityService.getCombinationActivity(id);
81   - if (combinationActivity == null) {
  78 + if (combinationActivity == null
  79 + || ObjectUtil.equal(combinationActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
82 80 return success(null);
83 81 }
84   - if (ObjectUtil.equal(combinationActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
85   - throw exception(COMBINATION_ACTIVITY_APP_STATUS_DISABLE);
86   - }
87   -
88 82 // 2、获取活动商品
89   - List<CombinationProductDO> products = activityService.getCombinationProductsByActivityIds(Arrays.asList(combinationActivity.getId()));
  83 + List<CombinationProductDO> products = activityService.getCombinationProductsByActivityId(combinationActivity.getId());
90 84 return success(CombinationActivityConvert.INSTANCE.convert3(combinationActivity, products));
91 85 }
92 86  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java
1 1 package cn.iocoder.yudao.module.promotion.controller.app.seckill;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.util.ObjectUtil;
4 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
... ... @@ -29,10 +30,8 @@ import org.springframework.web.bind.annotation.RestController;
29 30 import javax.annotation.Resource;
30 31 import java.util.List;
31 32  
32   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
33 33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
34 34 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
35   -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_APP_STATUS_CLOSED;
36 35  
37 36 @Tag(name = "用户 App - 秒杀活动")
38 37 @RestController
... ... @@ -48,6 +47,7 @@ public class AppSeckillActivityController {
48 47 @Resource
49 48 private ProductSpuApi spuApi;
50 49  
  50 + // TODO 芋艿:需要增加 spring cache
51 51 @GetMapping("/get-now")
52 52 @Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用")
53 53 public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
... ... @@ -61,7 +61,6 @@ public class AppSeckillActivityController {
61 61 List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIdAndStatus(configList.getId(), CommonStatusEnum.ENABLE.getStatus());
62 62 // 3 获取 spu 信息
63 63 List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId));
64   - // TODO 芋艿:需要增加 spring cache
65 64 return success(SeckillActivityConvert.INSTANCE.convert(configList, activityList, spuList));
66 65 }
67 66  
... ... @@ -70,7 +69,9 @@ public class AppSeckillActivityController {
70 69 public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) {
71 70 // 1. 查询满足当前阶段的活动
72 71 PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
73   -
  72 + if (CollUtil.isEmpty(pageResult.getList())) {
  73 + return success(PageResult.empty(pageResult.getTotal()));
  74 + }
74 75 // 2. 拼接数据
75 76 List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(pageResult.getList(), SeckillActivityDO::getSpuId));
76 77 return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList));
... ... @@ -88,16 +89,14 @@ public class AppSeckillActivityController {
88 89  
89 90 // 2. 获取活动
90 91 SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id);
91   - if (seckillActivity == null) {
  92 + if (seckillActivity == null
  93 + || ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
92 94 return success(null);
93 95 }
94   - if (ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
95   - throw exception(SECKILL_ACTIVITY_APP_STATUS_CLOSED);
96   - }
97 96  
98 97 // 3. 拼接数据
99   - List<SeckillProductDO> products = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
100   - return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, products, configList));
  98 + List<SeckillProductDO> productList = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
  99 + return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, productList, configList));
101 100 }
102 101  
103 102 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java
... ... @@ -28,7 +28,8 @@ public class AppSeckillConfigController {
28 28 @GetMapping("/list")
29 29 @Operation(summary = "获得秒杀时间段列表")
30 30 public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
31   - return success(SeckillConfigConvert.INSTANCE.convertList2(configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus())));
  31 + return success(SeckillConfigConvert.INSTANCE.convertList2(
  32 + configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus())));
32 33 }
33 34  
34 35 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/bargain/BargainActivityConvert.java
... ... @@ -73,9 +73,7 @@ public interface BargainActivityConvert {
73 73 // 拼接关联属性
74 74 Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
75 75 List<AppBargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
76   - findAndThen(spuMap, item.getSpuId(), spu -> {
77   - item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
78   - });
  76 + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
79 77 return item;
80 78 });
81 79 result.setList(list);
... ... @@ -88,9 +86,7 @@ public interface BargainActivityConvert {
88 86 List<AppBargainActivityRespVO> activityList = convertAppList(list);
89 87 Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
90 88 return CollectionUtils.convertList(activityList, item -> {
91   - findAndThen(spuMap, item.getSpuId(), spu -> {
92   - item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
93   - });
  89 + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
94 90 return item;
95 91 });
96 92 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
... ... @@ -61,9 +61,7 @@ public interface CombinationActivityConvert {
61 61 Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
62 62 PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
63 63 pageResult.getList().forEach(item -> {
64   - MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
65   - item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl());
66   - });
  64 + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
67 65 item.setProducts(convertList2(productList));
68 66 });
69 67 return pageResult;
... ... @@ -118,9 +116,7 @@ public interface CombinationActivityConvert {
118 116 List<AppCombinationActivityRespVO> activityList = convertAppList(list);
119 117 Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
120 118 return CollectionUtils.convertList(activityList, item -> {
121   - findAndThen(spuMap, item.getSpuId(), spu -> {
122   - item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
123   - });
  119 + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
124 120 return item;
125 121 });
126 122 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
... ... @@ -114,11 +114,8 @@ public interface SeckillActivityConvert {
114 114 PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult);
115 115 Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
116 116 List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
117   - findAndThen(spuMap, item.getSpuId(), spu -> {
118   - item.setPicUrl(spu.getPicUrl())
119   - .setMarketPrice(spu.getMarketPrice())
120   - .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
121   - });
  117 + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())
  118 + .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())));
122 119 return item;
123 120 });
124 121 result.setList(list);
... ... @@ -132,6 +129,7 @@ public interface SeckillActivityConvert {
132 129 default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
133 130 return convert2(seckillActivity)
134 131 .setProducts(convertList1(products))
  132 + // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点;
135 133 .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(),
136 134 "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合
137 135 .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(),
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
... ... @@ -38,7 +38,7 @@ public interface BargainActivityMapper extends BaseMapperX&lt;BargainActivityDO&gt; {
38 38 * @param count 扣减的库存数量
39 39 * @return 影响的行数
40 40 */
41   - default int updateActivityStock(Long id, int count) {
  41 + default int updateStock(Long id, int count) {
42 42 return update(null, new LambdaUpdateWrapper<BargainActivityDO>()
43 43 .eq(BargainActivityDO::getId, id)
44 44 .ge(BargainActivityDO::getStock, count)
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
... ... @@ -29,26 +29,12 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi
29 29 return selectList(CombinationActivityDO::getStatus, status);
30 30 }
31 31  
32   - /**
33   - * 查询 status 状态的活动分页
34   - *
35   - * @param pageParam 分页参数
36   - * @param status 状态
37   - * @return 活动分页
38   - */
39 32 default PageResult<CombinationActivityDO> selectPage(PageParam pageParam, Integer status) {
40 33 return selectPage(pageParam, new LambdaQueryWrapperX<CombinationActivityDO>()
41 34 .eq(CombinationActivityDO::getStatus, status));
42 35 }
43 36  
44   - /**
45   - * 查询 status 状态的活动分页
46   - *
47   - * @param status 状态
48   - * @param count 限制条数
49   - * @return 活动分页
50   - */
51   - default List<CombinationActivityDO> selectList(Integer status, Integer count) {
  37 + default List<CombinationActivityDO> selectListByStatus(Integer status, Integer count) {
52 38 return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
53 39 .eq(CombinationActivityDO::getStatus, status)
54 40 .last("LIMIT " + count));
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
... ... @@ -41,7 +41,7 @@ public interface SeckillActivityMapper extends BaseMapperX&lt;SeckillActivityDO&gt; {
41 41 * @param count 扣减的库存数量
42 42 * @return 影响的行数
43 43 */
44   - default int updateActivityStock(Long id, int count) {
  44 + default int updateStock(Long id, int count) {
45 45 return update(null, new LambdaUpdateWrapper<SeckillActivityDO>()
46 46 .eq(SeckillActivityDO::getId, id)
47 47 .gt(SeckillActivityDO::getTotalStock, 0)
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
... ... @@ -16,8 +16,13 @@ import java.util.List;
16 16 @Mapper
17 17 public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
18 18  
19   - default List<SeckillProductDO> selectListByActivityId(Long id) {
20   - return selectList(SeckillProductDO::getActivityId, id);
  19 + default List<SeckillProductDO> selectListByActivityId(Long activityId) {
  20 + return selectList(SeckillProductDO::getActivityId, activityId);
  21 + }
  22 +
  23 + default SeckillProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId) {
  24 + return selectOne(SeckillProductDO::getActivityId, activityId,
  25 + SeckillProductDO::getSkuId, skuId);
21 26 }
22 27  
23 28 default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) {
... ... @@ -31,7 +36,7 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; {
31 36 * @param count 扣减的库存数量
32 37 * @return 影响的行数
33 38 */
34   - default int updateActivityStock(Long id, int count) {
  39 + default int updateStock(Long id, int count) {
35 40 return update(null, new LambdaUpdateWrapper<SeckillProductDO>()
36 41 .eq(SeckillProductDO::getId, id)
37 42 .gt(SeckillProductDO::getStock, count)
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
... ... @@ -75,16 +75,18 @@ public class BargainActivityServiceImpl implements BargainActivityService {
75 75 }
76 76  
77 77 @Override
78   - @Transactional(rollbackFor = Exception.class)
79 78 public void updateBargainActivityStock(Long id, Integer count) {
80 79 // 查询砍价活动
81 80 BargainActivityDO activity = getBargainActivity(id);
82 81 if (activity == null) {
83 82 throw exception(BARGAIN_ACTIVITY_NOT_EXISTS);
84 83 }
  84 + if (count > activity.getStock()) {
  85 + throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
  86 + }
85 87  
86 88 // 更新砍价库存
87   - int updateCount = bargainActivityMapper.updateActivityStock(id, count);
  89 + int updateCount = bargainActivityMapper.updateStock(id, count);
88 90 if (updateCount == 0) {
89 91 throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
90 92 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
... ... @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationP
10 10  
11 11 import javax.validation.Valid;
12 12 import java.util.Collection;
  13 +import java.util.Collections;
13 14 import java.util.List;
14 15  
15 16 /**
... ... @@ -68,6 +69,16 @@ public interface CombinationActivityService {
68 69 /**
69 70 * 获得拼团活动商品列表
70 71 *
  72 + * @param activityId 拼团活动 id
  73 + * @return 拼团活动的商品列表
  74 + */
  75 + default List<CombinationProductDO> getCombinationProductsByActivityId(Long activityId) {
  76 + return getCombinationProductsByActivityIds(Collections.singletonList(activityId));
  77 + }
  78 +
  79 + /**
  80 + * 获得拼团活动商品列表
  81 + *
71 82 * @param activityIds 拼团活动 ids
72 83 * @return 拼团活动的商品列表
73 84 */
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
... ... @@ -247,7 +247,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
247 247  
248 248 @Override
249 249 public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) {
250   - return combinationActivityMapper.selectList(CommonStatusEnum.ENABLE.getStatus(), count);
  250 + return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count);
251 251 }
252 252  
253 253 @Override
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
... ... @@ -96,12 +96,15 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
96 96 return recordDO;
97 97 }
98 98  
  99 + // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先;
  100 +
99 101 @Override
100 102 @Transactional(rollbackFor = Exception.class)
101 103 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
102 104 // 1.1 校验拼团活动
103 105 CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
104 106 // 1.2 需要校验下,他当前是不是已经参加了该拼团;
  107 + // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount
105 108 CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
106 109 if (recordDO != null) {
107 110 throw exception(COMBINATION_RECORD_EXISTS);
... ... @@ -111,6 +114,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
111 114 if (CollUtil.isNotEmpty(recordDOList)) {
112 115 throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
113 116 }
  117 + // TODO @puhui999:有个开始时间未校验
114 118 // 1.4 校验当前活动是否过期
115 119 if (LocalDateTime.now().isAfter(activity.getEndTime())) {
116 120 throw exception(COMBINATION_RECORD_FAILED_TIME_END);
... ... @@ -128,6 +132,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
128 132 }
129 133 }
130 134  
  135 + // TODO @puhui999:单次限购
  136 +
131 137 // 2. 创建拼团记录
132 138 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
133 139 ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
... ... @@ -150,31 +150,25 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
150 150 @Override
151 151 @Transactional(rollbackFor = Exception.class)
152 152 public void updateSeckillStock(Long id, Long skuId, Integer count) {
153   - // 1、校验秒杀活动是否存在
  153 + // 1.1 校验活动库存是否充足
154 154 SeckillActivityDO seckillActivity = getSeckillActivity(id);
155   - // 1.1、校验库存是否充足
156   - if (seckillActivity.getTotalStock() < count) {
  155 + if (count > seckillActivity.getTotalStock()) {
157 156 throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
158 157 }
159   -
160   - // 2、获取活动商品
161   - List<SeckillProductDO> products = getSeckillProductListByActivityId(id);
162   - // 2.1、过滤出购买的商品
163   - SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(skuId, item.getSkuId()));
164   - // 2.2、检查活动商品库存是否充足
165   - boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < count) || (product.getStock() - count) < 0);
166   - if (isSufficient) {
  158 + // 1.2 校验商品库存是否充足
  159 + SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId);
  160 + if (product == null || count > product.getStock()) {
167 161 throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
168 162 }
169 163  
170   - // 3、更新活动商品库存
171   - int updateCount = seckillProductMapper.updateActivityStock(product.getId(), count);
  164 + // 2.1 更新活动商品库存
  165 + int updateCount = seckillProductMapper.updateStock(product.getId(), count);
172 166 if (updateCount == 0) {
173 167 throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
174 168 }
175 169  
176   - // 4、更新活动库存
177   - updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), count);
  170 + // 2.2 更新活动库存
  171 + updateCount = seckillActivityMapper.updateStock(seckillActivity.getId(), count);
178 172 if (updateCount == 0) {
179 173 throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
180 174 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/DictTypeConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.enums;
  2 +
  3 +/**
  4 + * Trade 字典类型的枚举类
  5 + *
  6 + * @author owen
  7 + */
  8 +public interface DictTypeConstants {
  9 +
  10 + String BROKERAGE_WITHDRAW_STATUS = "brokerage_withdraw_status"; // 佣金提现状态
  11 +
  12 +}
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -12,12 +12,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
12 12 public interface ErrorCodeConstants {
13 13  
14 14 // ========== Order 模块 1011000000 ==========
15   - ErrorCode ORDER_CREATE_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品 SKU 不存在");
16   - ErrorCode ORDER_CREATE_SPU_NOT_SALE = new ErrorCode(1011000002, "商品 SPU 不可售卖");
17   - ErrorCode ORDER_CREATE_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品 SKU 库存不足");
18   - ErrorCode ORDER_CREATE_SPU_NOT_FOUND = new ErrorCode(1011000005, "商品 SPU 不可售卖");
19   - ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在");
20   -
21 15 ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
22 16 ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
23 17 ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
... ... @@ -37,6 +31,7 @@ public interface ErrorCodeConstants {
37 31 ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价");
38 32 ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1011000027, "支付订单调价失败,原因:价格没有变化");
39 33 ErrorCode ORDER_UPDATE_PRICE_FAIL_NOT_ITEM = new ErrorCode(1011000028, "支付订单调价失败,原因:订单项不存在");
  34 + ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
40 35  
41 36 // ========== After Sale 模块 1011000100 ==========
42 37 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
... ... @@ -58,8 +53,8 @@ public interface ErrorCodeConstants {
58 53  
59 54 // ========== Price 相关 1011003000 ============
60 55 ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
61   - ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY = new ErrorCode(1011003001, "计算快递运费异常,收件人地址编号为空");
62 56 ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
  57 + ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
63 58  
64 59 // ========== 物流 Express 模块 1011004000 ==========
65 60 ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");
... ... @@ -92,5 +87,7 @@ public interface ErrorCodeConstants {
92 87 // ========== 分销提现 模块 1011008000 ==========
93 88 ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1011008000, "佣金提现记录不存在");
94 89 ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1011008001, "佣金提现记录状态不是审核中");
  90 + ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1011008002, "提现金额不能低于 {} 元");
  91 + ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1011008003, "您当前最多可提现 {} 元");
95 92  
96 93 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java
... ... @@ -17,6 +17,7 @@ public enum BrokerageRecordBizTypeEnum implements IntArrayValuable {
17 17  
18 18 ORDER(1, "获得推广佣金", "获得推广佣金 {}", true),
19 19 WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false),
  20 + WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回返还佣金 {}", true),
20 21 ;
21 22  
22 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray();
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/delivery/DeliveryExpressChargeModeEnum.java
... ... @@ -16,7 +16,7 @@ import java.util.Arrays;
16 16 @Getter
17 17 public enum DeliveryExpressChargeModeEnum implements IntArrayValuable {
18 18  
19   - PIECE(1, "按件"),
  19 + COUNT(1, "按件"),
20 20 WEIGHT(2,"按重量"),
21 21 VOLUME(3, "按体积");
22 22  
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/delivery/DeliveryTypeEnum.java
... ... @@ -15,16 +15,15 @@ import java.util.Arrays;
15 15 @AllArgsConstructor
16 16 public enum DeliveryTypeEnum implements IntArrayValuable {
17 17  
18   - NULL(0, "无需物流"),
19 18 EXPRESS(1, "快递发货"),
20 19 PICK_UP(2, "用户自提"),;
21 20  
22   - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DeliveryTypeEnum::getMode).toArray();
  21 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DeliveryTypeEnum::getType).toArray();
23 22  
24 23 /**
25 24 * 配送方式
26 25 */
27   - private final Integer mode;
  26 + private final Integer type;
28 27 /**
29 28 * 状态名
30 29 */
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderOperateTypeEnum.java
... ... @@ -14,7 +14,10 @@ import lombok.RequiredArgsConstructor;
14 14 public enum TradeOrderOperateTypeEnum {
15 15  
16 16 MEMBER_CREATE(1, "用户下单"),
17   - TEST(2, "用户({nickname})做了({thing})"),
  17 + MEMBER_RECEIVE(30, "用户已收货"),
  18 + MEMBER_COMMENT(31, "用户评价"),
  19 + MEMBER_CANCEL(40, "取消订单"),
  20 + MEMBER_DELETE(41, "删除订单"),
18 21 ;
19 22  
20 23 /**
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
... ... @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
8 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
9 9 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
10 10 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*;
  11 +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO;
11 12 import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
12 13 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
13 14 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
14 15 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
15   -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespVO;
16 16 import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService;
17 17 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
18 18 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageRecordController.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
6 6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO;
8   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO;
9   -import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert;
10   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO;
11   -import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
  7 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
  8 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordRespVO;
  9 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
  10 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
  11 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
12 12 import io.swagger.v3.oas.annotations.Operation;
13 13 import io.swagger.v3.oas.annotations.Parameter;
14 14 import io.swagger.v3.oas.annotations.tags.Tag;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageUserController.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
6 6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*;
8   -import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert;
9   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  7 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.*;
  8 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert;
  9 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
10 10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
11 11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
  12 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
  13 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
12 14 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
13   -import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
14   -import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
  15 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
  16 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
  17 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
15 18 import io.swagger.v3.oas.annotations.Operation;
16 19 import io.swagger.v3.oas.annotations.Parameter;
17 20 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -38,6 +41,8 @@ public class BrokerageUserController {
38 41 private BrokerageUserService brokerageUserService;
39 42 @Resource
40 43 private BrokerageRecordService brokerageRecordService;
  44 + @Resource
  45 + private BrokerageWithdrawService brokerageWithdrawService;
41 46  
42 47 @Resource
43 48 private MemberUserApi memberUserApi;
... ... @@ -87,6 +92,7 @@ public class BrokerageUserController {
87 92 Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
88 93 // 查询用户信息
89 94 Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
  95 + // TODO @疯狂:看看下面两个 getBrokerageUserCountByBindUserId、getWithdrawSummaryByUserId 有没可能一次性出结果,不然 n 次有点太花性能了;
90 96 // 合计分佣订单
91 97 Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap = convertMap(userIds,
92 98 userId -> userId,
... ... @@ -96,10 +102,13 @@ public class BrokerageUserController {
96 102 Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
97 103 userId -> userId,
98 104 userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
99   -
100   - // todo 合计提现
101   -
102   - return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap));
  105 + // 合计提现
  106 + Map<Long, UserWithdrawSummaryBO> withdrawMap = convertMap(userIds,
  107 + userId -> userId,
  108 + userId -> brokerageWithdrawService.getWithdrawSummaryByUserId(userId, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS));
  109 + // 拼接返回
  110 + return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
  111 + userOrderSummaryMap, withdrawMap));
103 112 }
104 113  
105 114 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/BrokerageWithdrawController.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
6 6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRejectReqVO;
8   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawPageReqVO;
9   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRespVO;
10   -import cn.iocoder.yudao.module.trade.convert.brokerage.withdraw.BrokerageWithdrawConvert;
11   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
  7 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRejectReqVO;
  8 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
  9 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
  10 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
  11 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
12 12 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
13   -import cn.iocoder.yudao.module.trade.service.brokerage.withdraw.BrokerageWithdrawService;
  13 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
14 14 import io.swagger.v3.oas.annotations.Operation;
15 15 import io.swagger.v3.oas.annotations.Parameter;
16 16 import io.swagger.v3.oas.annotations.tags.Tag;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordBaseVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordPageReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/record/BrokerageRecordRespVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserBaseVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserClearBrokerageUserReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserPageReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserRespVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserUpdateBrokerageEnabledReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/user/BrokerageUserUpdateBrokerageUserReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawBaseVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawPageReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawPageReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawRejectReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRejectReqVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/withdraw/vo/BrokerageWithdrawRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java
1   -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo;
  1 +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java
... ... @@ -19,6 +19,17 @@ import java.util.List;
19 19 */
20 20 @Data
21 21 public class TradeConfigBaseVO {
  22 + /**
  23 + * 是否启用全场包邮
  24 + */
  25 + @Schema(description = "是否启用全场包邮", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  26 + @NotNull(message = "是否启用全场包邮不能为空")
  27 + private Boolean deliveryExpressFreeEnabled;
  28 +
  29 + @Schema(description = "全场包邮的最小金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
  30 + @NotNull(message = "全场包邮的最小金额不能为空")
  31 + @PositiveOrZero(message = "全场包邮的最小金额不能是负数")
  32 + private Integer deliveryExpressFreePrice;
22 33  
23 34 // ========== 分销相关 ==========
24 35  
... ... @@ -37,7 +48,7 @@ public class TradeConfigBaseVO {
37 48 private Integer brokerageBindMode;
38 49  
39 50 @Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]")
40   - private List<String> brokeragePostUrls;
  51 + private List<String> brokeragePosterUrls;
41 52  
42 53 @Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
43 54 @NotNull(message = "一级返佣比例不能为空")
... ... @@ -54,6 +65,11 @@ public class TradeConfigBaseVO {
54 65 @PositiveOrZero(message = "用户提现最低金额不能是负数")
55 66 private Integer brokerageWithdrawMinPrice;
56 67  
  68 + @Schema(description = "用户提现手续费百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
  69 + @NotNull(message = "用户提现手续费百分比不能为空")
  70 + @PositiveOrZero(message = "用户提现手续费百分比不能是负数")
  71 + private Integer brokerageWithdrawFeePercent;
  72 +
57 73 @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
58 74 @NotEmpty(message = "提现银行不能为空")
59 75 private List<Integer> brokerageBankNames;
... ... @@ -66,6 +82,6 @@ public class TradeConfigBaseVO {
66 82 @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
67 83 @NotNull(message = "提现方式不能为空")
68 84 @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}")
69   - private List<Integer> brokerageWithdrawType;
  85 + private List<Integer> brokerageWithdrawTypes;
70 86  
71 87 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
... ... @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
7 7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
8 8 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
9   -import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
  9 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
  10 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
  11 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
10 12 import io.swagger.v3.oas.annotations.Operation;
11 13 import io.swagger.v3.oas.annotations.tags.Tag;
12 14 import lombok.extern.slf4j.Slf4j;
... ... @@ -18,11 +20,9 @@ import org.springframework.web.bind.annotation.RestController;
18 20  
19 21 import javax.annotation.Resource;
20 22 import javax.validation.Valid;
21   -import java.time.LocalDateTime;
22 23  
23 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
24 25 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
25   -import static java.util.Arrays.asList;
26 26  
27 27 @Tag(name = "用户 APP - 分销用户")
28 28 @RestController
... ... @@ -31,30 +31,21 @@ import static java.util.Arrays.asList;
31 31 @Slf4j
32 32 public class AppBrokerageRecordController {
33 33 @Resource
34   - private BrokerageUserService brokerageUserService;
  34 + private BrokerageRecordService brokerageRecordService;
35 35  
36   - // TODO 芋艿:临时 mock =>
37 36 @GetMapping("/page")
38 37 @Operation(summary = "获得分销记录分页")
39 38 @PreAuthenticated
40 39 public CommonResult<PageResult<AppBrokerageRecordRespVO>> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) {
41   - AppBrokerageRecordRespVO vo1 = new AppBrokerageRecordRespVO()
42   - .setId(1L).setPrice(10).setTitle("收到钱").setCreateTime(LocalDateTime.now())
43   - .setFinishTime(LocalDateTime.now());
44   - AppBrokerageRecordRespVO vo2 = new AppBrokerageRecordRespVO()
45   - .setId(2L).setPrice(-20).setTitle("提现钱").setCreateTime(LocalDateTime.now())
46   - .setFinishTime(LocalDateTime.now());
47   - return success(new PageResult<>(asList(vo1, vo2), 10L));
  40 + PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(
  41 + BrokerageRecordConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
  42 + return success(BrokerageRecordConvert.INSTANCE.convertPage02(pageResult));
48 43 }
49 44  
50 45 @GetMapping("/get-product-brokerage-price")
51 46 @Operation(summary = "获得商品的分销金额")
52 47 public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
53   - AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO();
54   - respVO.setEnabled(brokerageUserService.getUserBrokerageEnabled(getLoginUserId()));
55   - respVO.setBrokerageMinPrice(1);
56   - respVO.setBrokerageMaxPrice(2);
57   - return success(respVO);
  48 + return success(brokerageRecordService.calculateProductBrokeragePrice(spuId, getLoginUserId()));
58 49 }
59 50  
60 51 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java
1 1 package cn.iocoder.yudao.module.trade.controller.app.brokerage;
2 2  
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  7 +import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
  8 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
6 9 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*;
7   -import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
  10 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
  11 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert;
  12 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
  13 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
  14 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
  15 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
  16 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
  17 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
  18 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
8 19 import io.swagger.v3.oas.annotations.Operation;
9 20 import io.swagger.v3.oas.annotations.Parameter;
10 21 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -16,11 +27,13 @@ import org.springframework.web.bind.annotation.*;
16 27 import javax.annotation.Resource;
17 28 import javax.validation.Valid;
18 29 import java.time.LocalDateTime;
  30 +import java.util.Map;
  31 +import java.util.Optional;
19 32  
20 33 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  34 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
21 35 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
22 36 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
23   -import static java.util.Arrays.asList;
24 37  
25 38 @Tag(name = "用户 APP - 分销用户")
26 39 @RestController
... ... @@ -30,16 +43,24 @@ import static java.util.Arrays.asList;
30 43 public class AppBrokerageUserController {
31 44 @Resource
32 45 private BrokerageUserService brokerageUserService;
  46 + @Resource
  47 + private BrokerageRecordService brokerageRecordService;
  48 + @Resource
  49 + private BrokerageWithdrawService brokerageWithdrawService;
  50 +
  51 + @Resource
  52 + private MemberUserApi memberUserApi;
33 53  
34   - // TODO 芋艿:临时 mock =>
35 54 @GetMapping("/get")
36 55 @Operation(summary = "获得个人分销信息")
37 56 @PreAuthenticated
38 57 public CommonResult<AppBrokerageUserRespVO> getBrokerageUser() {
  58 + Optional<BrokerageUserDO> user = Optional.ofNullable(brokerageUserService.getBrokerageUser(getLoginUserId()));
  59 + // 返回数据
39 60 AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO()
40   - .setBrokerageEnabled(true)
41   - .setPrice(2000)
42   - .setFrozenPrice(3000);
  61 + .setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(false))
  62 + .setBrokeragePrice(user.map(BrokerageUserDO::getBrokeragePrice).orElse(0))
  63 + .setFrozenPrice(user.map(BrokerageUserDO::getFrozenPrice).orElse(0));
43 64 return success(respVO);
44 65 }
45 66  
... ... @@ -47,88 +68,70 @@ public class AppBrokerageUserController {
47 68 @Operation(summary = "绑定推广员")
48 69 @PreAuthenticated
49 70 public CommonResult<Boolean> bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) {
50   - return success(brokerageUserService.bindBrokerageUser(getLoginUserId(), reqVO.getBindUserId(), false));
  71 + MemberUserRespDTO user = memberUserApi.getUser(getLoginUserId());
  72 + return success(brokerageUserService.bindBrokerageUser(user.getId(), reqVO.getBindUserId(), user.getCreateTime()));
51 73 }
52 74  
53   - // TODO 芋艿:临时 mock =>
54 75 @GetMapping("/get-summary")
55 76 @Operation(summary = "获得个人分销统计")
56 77 @PreAuthenticated
57 78 public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() {
  79 + Long userId = getLoginUserId();
  80 + // TODO @疯狂:后面这种,要不也改成 convert;感觉 controller 这样更容易看到整体;核心其实是 86、8/87、9/90、9/91 这阶段
  81 + // 统计 yesterdayPrice、withdrawPrice、firstBrokerageUserCount、secondBrokerageUserCount 字段
  82 + LocalDateTime yesterday = LocalDateTime.now().minusDays(1);
  83 + LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday);
  84 + LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday);
58 85 AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO()
59   - .setYesterdayPrice(1)
60   - .setBrokeragePrice(2)
61   - .setFrozenPrice(3)
62   - .setWithdrawPrice(4)
63   - .setFirstBrokerageUserCount(166)
64   - .setSecondBrokerageUserCount(233);
  86 + .setYesterdayPrice(brokerageRecordService.getSummaryPriceByUserId(userId, BrokerageRecordBizTypeEnum.ORDER.getType(), beginTime, endTime))
  87 + .setWithdrawPrice(Optional.ofNullable(brokerageWithdrawService.getWithdrawSummaryByUserId(userId, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS))
  88 + .map(UserWithdrawSummaryBO::getPrice).orElse(0))
  89 + .setBrokeragePrice(0).setFrozenPrice(0)
  90 + .setFirstBrokerageUserCount(brokerageUserService.getBrokerageUserCountByBindUserId(userId, 1))
  91 + .setSecondBrokerageUserCount(brokerageUserService.getBrokerageUserCountByBindUserId(userId, 2));
  92 + // 设置 brokeragePrice、frozenPrice 字段
  93 + Optional.ofNullable(brokerageUserService.getBrokerageUser(userId))
  94 + .ifPresent(user -> respVO.setBrokeragePrice(user.getBrokeragePrice()).setFrozenPrice(user.getFrozenPrice()));
65 95 return success(respVO);
66 96 }
67 97  
68   - // TODO 芋艿:临时 mock =>
69 98 @GetMapping("/rank-page-by-user-count")
70 99 @Operation(summary = "获得分销用户排行分页(基于用户量)")
71 100 @PreAuthenticated
72 101 public CommonResult<PageResult<AppBrokerageUserRankByUserCountRespVO>> getBrokerageUserRankPageByUserCount(AppBrokerageUserRankPageReqVO pageReqVO) {
73   - AppBrokerageUserRankByUserCountRespVO vo1 = new AppBrokerageUserRankByUserCountRespVO()
74   - .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
75   - .setBrokerageUserCount(10);
76   - AppBrokerageUserRankByUserCountRespVO vo2 = new AppBrokerageUserRankByUserCountRespVO()
77   - .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
78   - .setBrokerageUserCount(6);
79   - AppBrokerageUserRankByUserCountRespVO vo3 = new AppBrokerageUserRankByUserCountRespVO()
80   - .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
81   - .setBrokerageUserCount(4);
82   - AppBrokerageUserRankByUserCountRespVO vo4 = new AppBrokerageUserRankByUserCountRespVO()
83   - .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
84   - .setBrokerageUserCount(4);
85   - return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L));
  102 + // 分页查询
  103 + PageResult<AppBrokerageUserRankByUserCountRespVO> pageResult = brokerageUserService.getBrokerageUserRankPageByUserCount(pageReqVO);
  104 + // 拼接数据
  105 + Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByUserCountRespVO::getId));
  106 + return success(BrokerageUserConvert.INSTANCE.convertPage03(pageResult, userMap));
86 107 }
87 108  
88   - // TODO 芋艿:临时 mock =>
89 109 @GetMapping("/rank-page-by-price")
90 110 @Operation(summary = "获得分销用户排行分页(基于佣金)")
91 111 @PreAuthenticated
92 112 public CommonResult<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) {
93   - AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO()
94   - .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
95   - .setBrokeragePrice(10);
96   - AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO()
97   - .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
98   - .setBrokeragePrice(6);
99   - AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO()
100   - .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
101   - .setBrokeragePrice(4);
102   - AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO()
103   - .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
104   - .setBrokeragePrice(4);
105   - return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L));
  113 + // 分页查询
  114 + PageResult<AppBrokerageUserRankByPriceRespVO> pageResult = brokerageRecordService.getBrokerageUserChildSummaryPageByPrice(pageReqVO);
  115 + // 拼接数据
  116 + Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByPriceRespVO::getId));
  117 + return success(BrokerageRecordConvert.INSTANCE.convertPage03(pageResult, userMap));
106 118 }
107 119  
108   - // TODO 芋艿:临时 mock =>
109 120 @GetMapping("/child-summary-page")
110 121 @Operation(summary = "获得下级分销统计分页")
111 122 @PreAuthenticated
112 123 public CommonResult<PageResult<AppBrokerageUserChildSummaryRespVO>> getBrokerageUserChildSummaryPage(
113 124 AppBrokerageUserChildSummaryPageReqVO pageReqVO) {
114   - AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO()
115   - .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
116   - .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30)
117   - .setBrokerageTime(LocalDateTime.now());
118   - AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO()
119   - .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg")
120   - .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40)
121   - .setBrokerageTime(LocalDateTime.now());
122   - return success(new PageResult<>(asList(vo1, vo2), 10L));
  125 + PageResult<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserService.getBrokerageUserChildSummaryPage(pageReqVO, getLoginUserId());
  126 + return success(pageResult);
123 127 }
124 128  
125   - // TODO 芋艿:临时 mock =>
126 129 @GetMapping("/get-rank-by-price")
127 130 @Operation(summary = "获得分销用户排行(基于佣金)")
128 131 @Parameter(name = "times", description = "时间段", required = true)
129   - public CommonResult<Integer> bindBrokerageUser(
  132 + public CommonResult<Integer> getRankByPrice(
130 133 @RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) {
131   - return success(1);
  134 + return success(brokerageRecordService.getUserRankByPrice(getLoginUserId(), times));
132 135 }
133 136  
134 137 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java
... ... @@ -3,19 +3,24 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  6 +import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
6 7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
  8 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
7 9 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
  10 +import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
  11 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
  12 +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
8 13 import io.swagger.v3.oas.annotations.Operation;
9 14 import io.swagger.v3.oas.annotations.tags.Tag;
10 15 import lombok.extern.slf4j.Slf4j;
11 16 import org.springframework.validation.annotation.Validated;
12 17 import org.springframework.web.bind.annotation.*;
13 18  
  19 +import javax.annotation.Resource;
14 20 import javax.validation.Valid;
15   -import java.time.LocalDateTime;
16 21  
17 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
18   -import static java.util.Arrays.asList;
  23 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
19 24  
20 25 @Tag(name = "用户 APP - 分销提现")
21 26 @RestController
... ... @@ -24,24 +29,27 @@ import static java.util.Arrays.asList;
24 29 @Slf4j
25 30 public class AppBrokerageWithdrawController {
26 31  
27   - // TODO 芋艿:临时 mock =>
  32 + @Resource
  33 + private BrokerageWithdrawService brokerageWithdrawService;
  34 +
  35 + @Resource
  36 + private DictDataApi dictDataApi;
  37 +
28 38 @GetMapping("/page")
29 39 @Operation(summary = "获得分销提现分页")
30 40 @PreAuthenticated
31   - public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage() {
32   - AppBrokerageWithdrawRespVO vo1 = new AppBrokerageWithdrawRespVO()
33   - .setId(1L).setStatus(10).setPrice(10).setStatusName("审批通过").setCreateTime(LocalDateTime.now());
34   - AppBrokerageWithdrawRespVO vo2 = new AppBrokerageWithdrawRespVO()
35   - .setId(2L).setStatus(0).setPrice(20).setStatusName("审批中").setCreateTime(LocalDateTime.now());
36   - return success(new PageResult<>(asList(vo1, vo2), 10L));
  41 + public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
  42 + // 分页查询
  43 + PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
  44 + BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
  45 + return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
37 46 }
38 47  
39   - // TODO 芋艿:临时 mock =>
40 48 @PostMapping("/create")
41 49 @Operation(summary = "创建分销提现")
42 50 @PreAuthenticated
43 51 public CommonResult<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) {
44   - return success(1L);
  52 + return success(brokerageWithdrawService.createBrokerageWithdraw(createReqVO, getLoginUserId()));
45 53 }
46 54  
47 55 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java
... ... @@ -27,7 +27,7 @@ public class AppBrokerageUserChildSummaryRespVO {
27 27 @Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
28 28 private Integer brokerageUserCount;
29 29  
30   - @Schema(description = "成为分销员时间", requiredMode = Schema.RequiredMode.REQUIRED)
  30 + @Schema(description = "绑定推广员的时间", requiredMode = Schema.RequiredMode.REQUIRED)
31 31 private LocalDateTime brokerageTime;
32 32  
33 33 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java
... ... @@ -20,9 +20,9 @@ public class AppBrokerageUserMySummaryRespVO {
20 20 private Integer frozenPrice;
21 21  
22 22 @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
23   - private Integer firstBrokerageUserCount;
  23 + private Long firstBrokerageUserCount;
24 24  
25 25 @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
26   - private Integer secondBrokerageUserCount;
  26 + private Long secondBrokerageUserCount;
27 27  
28 28 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java
... ... @@ -11,7 +11,7 @@ public class AppBrokerageUserRespVO {
11 11 private Boolean brokerageEnabled;
12 12  
13 13 @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
14   - private Integer price;
  14 + private Integer brokeragePrice;
15 15  
16 16 @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
17 17 private Integer frozenPrice;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java
... ... @@ -8,8 +8,9 @@ import lombok.Data;
8 8 import org.hibernate.validator.constraints.URL;
9 9  
10 10 import javax.validation.Validator;
11   -import javax.validation.constraints.Min;
12 11 import javax.validation.constraints.NotBlank;
  12 +import javax.validation.constraints.NotNull;
  13 +import javax.validation.constraints.PositiveOrZero;
13 14  
14 15 @Schema(description = "用户 App - 分销提现创建 Request VO")
15 16 @Data
... ... @@ -20,7 +21,8 @@ public class AppBrokerageWithdrawCreateReqVO {
20 21 private Integer type;
21 22  
22 23 @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
23   - @Min(value = 1, message = "提现金额不能小于 1")
  24 + @PositiveOrZero(message = "提现金额不能小于 0")
  25 + @NotNull(message = "提现金额不能为空")
24 26 private Integer price;
25 27  
26 28 // ========== 银行卡、微信、支付宝 提现相关字段 ==========
... ... @@ -41,7 +43,7 @@ public class AppBrokerageWithdrawCreateReqVO {
41 43 @NotBlank(message = "持卡人姓名不能为空", groups = {Bank.class})
42 44 private String name;
43 45 @Schema(description = "提现银行", example = "1")
44   - @NotBlank(message = "提现银行不能为空", groups = {Bank.class})
  46 + @NotNull(message = "提现银行不能为空", groups = {Bank.class})
45 47 private Integer bankName;
46 48 @Schema(description = "开户地址", example = "海淀支行")
47 49 private String bankAddress;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
  6 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
  7 +import io.swagger.v3.oas.annotations.media.Schema;
  8 +import lombok.Data;
  9 +
  10 +@Schema(description = "应用 App - 分销提现分页 Request VO")
  11 +@Data
  12 +public class AppBrokerageWithdrawPageReqVO extends PageParam {
  13 +
  14 + @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  15 + @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "类型必须是 {value}")
  16 + private Integer type;
  17 +
  18 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + @InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
  20 + private Integer status;
  21 +
  22 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/AppTradeConfigController.java
1 1 package cn.iocoder.yudao.module.trade.controller.app.config;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.module.trade.controller.app.config.vo.AppTradeConfigRespVO;
  6 +import cn.iocoder.yudao.module.trade.convert.config.TradeConfigConvert;
  7 +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
  8 +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
  9 +import io.swagger.v3.oas.annotations.Operation;
5 10 import io.swagger.v3.oas.annotations.tags.Tag;
6 11 import lombok.RequiredArgsConstructor;
7 12 import lombok.extern.slf4j.Slf4j;
... ... @@ -10,8 +15,9 @@ import org.springframework.web.bind.annotation.GetMapping;
10 15 import org.springframework.web.bind.annotation.RequestMapping;
11 16 import org.springframework.web.bind.annotation.RestController;
12 17  
  18 +import javax.annotation.Resource;
  19 +
13 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
14   -import static java.util.Arrays.asList;
15 21  
16 22 @Tag(name = "用户 App - 交易配置")
17 23 @RestController
... ... @@ -21,17 +27,14 @@ import static java.util.Arrays.asList;
21 27 @Slf4j
22 28 public class AppTradeConfigController {
23 29  
  30 + @Resource
  31 + private TradeConfigService tradeConfigService;
  32 +
24 33 @GetMapping("/get")
  34 + @Operation(summary = "获得交易配置")
25 35 public CommonResult<AppTradeConfigRespVO> getTradeConfig() {
26   - AppTradeConfigRespVO respVO = new AppTradeConfigRespVO();
27   - respVO.setBrokeragePosterUrls(asList(
28   - "https://api.java.crmeb.net/crmebimage/product/2020/08/03/755bf516b1ca4b6db3bfeaa4dd5901cdh71kob20re.jpg",
29   - "https://api.java.crmeb.net/crmebimage/maintain/2021/03/01/406d729b84ed4ec9a2171bfcf6fd0634ughzbz9kfi.jpg",
30   - "https://api.java.crmeb.net/crmebimage/maintain/2021/03/01/efb1e4e7fe604fe1988b4213ce08cb11tdsyijtd2r.jpg"
31   - ));
32   - respVO.setBrokerageFrozenDays(10);
33   - respVO.setBrokerageWithdrawMinPrice(100);
34   - return success(respVO);
  36 + TradeConfigDO tradeConfig = ObjUtil.defaultIfNull(tradeConfigService.getTradeConfig(), new TradeConfigDO());
  37 + return success(TradeConfigConvert.INSTANCE.convert02(tradeConfig));
35 38 }
36 39  
37 40 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/config/vo/AppTradeConfigRespVO.java
... ... @@ -18,4 +18,7 @@ public class AppTradeConfigRespVO {
18 18 @Schema(description = "佣金提现最小金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
19 19 private Integer brokerageWithdrawMinPrice;
20 20  
  21 + @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
  22 + private List<Integer> brokerageWithdrawTypes;
  23 +
21 24 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/AppDeliverConfigController.java
... ... @@ -17,6 +17,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
17 17 @Validated
18 18 public class AppDeliverConfigController {
19 19  
  20 + // TODO @芋艿:这里后面干掉,合并到 AppTradeConfigController 中
20 21 @GetMapping("/get")
21 22 @Operation(summary = "获得配送配置")
22 23 public CommonResult<AppDeliveryConfigRespVO> getDeliveryConfig() {
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http
... ... @@ -8,14 +8,15 @@ GET {{appApi}}/trade/order/settlement?type=0&amp;items[0].cartId=50&amp;couponId=1
8 8 Authorization: Bearer {{appToken}}
9 9 tenant-id: {{appTenentId}}
10 10  
11   -### /trade-order/create 创建订单(基于商品)
  11 +### /trade-order/create 创建订单(基于商品)【快递】
12 12 POST {{appApi}}/trade/order/create
13 13 Content-Type: application/json
14 14 Authorization: Bearer {{appToken}}
15 15 tenant-id: {{appTenentId}}
16 16  
17 17 {
18   - "type": 0,
  18 + "pointStatus": true,
  19 + "deliveryType": 1,
19 20 "addressId": 21,
20 21 "items": [
21 22 {
... ... @@ -26,6 +27,27 @@ tenant-id: {{appTenentId}}
26 27 "remark": "我是备注"
27 28 }
28 29  
  30 +### /trade-order/create 创建订单(基于商品)【自提】
  31 +POST {{appApi}}/trade/order/create
  32 +Content-Type: application/json
  33 +Authorization: Bearer {{appToken}}
  34 +tenant-id: {{appTenentId}}
  35 +
  36 +{
  37 + "pointStatus": true,
  38 + "deliveryType": 2,
  39 + "pickUpStoreId": 1,
  40 + "items": [
  41 + {
  42 + "skuId": 1,
  43 + "count": 2
  44 + }
  45 + ],
  46 + "remark": "我是备注",
  47 + "receiverName": "土豆",
  48 + "receiverMobile": "15601691300"
  49 +}
  50 +
29 51 ### 获得订单交易的分页
30 52 GET {{appApi}}/trade/order/page?pageNo=1&pageSize=10
31 53 Authorization: Bearer {{appToken}}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
1 1 package cn.iocoder.yudao.module.trade.controller.app.order;
2 2  
3   -import cn.hutool.core.map.MapUtil;
4 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
... ... @@ -12,11 +11,8 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
12 11 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
13 12 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
14 13 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
15   -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderOperateTypeEnum;
16 14 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
17 15 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
18   -import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog;
19   -import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils;
20 16 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
21 17 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
22 18 import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
... ... @@ -65,10 +61,7 @@ public class AppTradeOrderController {
65 61 @PostMapping("/create")
66 62 @Operation(summary = "创建订单")
67 63 @PreAuthenticated
68   - @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.TEST)
69   - public CommonResult<AppTradeOrderCreateRespVO> createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO) {
70   - TradeOrderLogUtils.setOrderInfo(10L, 1, 2,
71   - MapUtil.<String, Object>builder().put("nickname", "小明").put("thing", "种土豆").build());
  64 + public CommonResult<AppTradeOrderCreateRespVO> createOrder(@Valid @RequestBody AppTradeOrderCreateReqVO createReqVO) {
72 65 TradeOrderDO order = tradeOrderUpdateService.createOrder(getLoginUserId(), getClientIP(), createReqVO);
73 66 return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId()));
74 67 }
... ... @@ -163,7 +156,7 @@ public class AppTradeOrderController {
163 156 @Operation(summary = "删除交易订单")
164 157 @Parameter(name = "id", description = "交易订单编号")
165 158 public CommonResult<Boolean> deleteOrder(@RequestParam("id") Long id) {
166   - // TODO @芋艿:未实现,mock 用
  159 + tradeOrderUpdateService.deleteOrder(getLoginUserId(), id);
167 160 return success(true);
168 161 }
169 162  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java
1 1 package cn.iocoder.yudao.module.trade.controller.app.order.vo;
2 2  
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
3 4 import io.swagger.v3.oas.annotations.media.Schema;
4 5 import lombok.Data;
5 6  
  7 +import javax.validation.constraints.AssertTrue;
  8 +
6 9 @Schema(description = "用户 App - 交易订单创建 Request VO")
7 10 @Data
8 11 public class AppTradeOrderCreateReqVO extends AppTradeOrderSettlementReqVO {
... ... @@ -10,4 +13,10 @@ public class AppTradeOrderCreateReqVO extends AppTradeOrderSettlementReqVO {
10 13 @Schema(description = "备注", example = "这个是我的订单哟")
11 14 private String remark;
12 15  
  16 + @AssertTrue(message = "配送方式不能为空")
  17 + @JsonIgnore
  18 + public boolean isDeliveryTypeNotNull() {
  19 + return getDeliveryType() != null;
  20 + }
  21 +
13 22 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
... ... @@ -30,7 +30,7 @@ public class AppTradeOrderSettlementReqVO {
30 30 private Boolean pointStatus;
31 31  
32 32 // ========== 配送相关相关字段 ==========
33   - @Schema(description = "配送方式", required = true, example = "1")
  33 + @Schema(description = "配送方式", example = "1")
34 34 @InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确")
35 35 private Integer deliveryType;
36 36  
... ... @@ -62,6 +62,8 @@ public class AppTradeOrderSettlementReqVO {
62 62 @Schema(description = "砍价活动编号", example = "123")
63 63 private Long bargainActivityId;
64 64  
  65 + // TODO @puhui999:可以写个参数校验,如果 seckillActivityId 或 combinationActivityId 或 combinationHeadId 的情况,items 应该只有一个
  66 +
65 67 @Data
66 68 @Schema(description = "用户 App - 商品项")
67 69 @Valid
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
... ... @@ -82,6 +82,9 @@ public class AppTradeOrderSettlementRespVO {
82 82 @Schema(description = "积分抵扣的金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
83 83 private Integer pointPrice;
84 84  
  85 + @Schema(description = "VIP 减免金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
  86 + private Integer vipPrice;
  87 +
85 88 @Schema(description = "实际支付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "450")
86 89 private Integer payPrice;
87 90  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
6 6 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
7 7 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDetailRespVO;
8 8 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
  9 +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO;
9 10 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
10 11 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
11 12 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO;
... ... @@ -15,7 +16,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
15 16 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO;
16 17 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
17 18 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
18   -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespVO;
19 19 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
20 20 import org.mapstruct.Mapper;
21 21 import org.mapstruct.Mapping;
... ... @@ -68,7 +68,7 @@ public interface TradeAfterSaleConvert {
68 68 PageResult<AppTradeAfterSaleRespVO> convertPage02(PageResult<TradeAfterSaleDO> page);
69 69  
70 70 List<TradeAfterSaleLogRespVO> convertList(List<TradeAfterSaleLogDO> list);
71   -
  71 +
72 72 default TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, TradeOrderDO order, List<TradeOrderItemDO> orderItems,
73 73 MemberUserRespDTO user, List<TradeAfterSaleLogRespVO> logs) {
74 74 TradeAfterSaleDetailRespVO respVO = convert(afterSale, orderItems);
... ... @@ -81,7 +81,7 @@ public interface TradeAfterSaleConvert {
81 81 return respVO;
82 82 }
83 83  
84   - List<cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespVO> list);
  84 + List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespVO> list);
85 85 @Mapping(target = "id", source = "afterSale.id")
86 86 TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List<TradeOrderItemDO> orderItems);
87 87 TradeOrderBaseVO convert(TradeOrderDO order);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java
1   -package cn.iocoder.yudao.module.trade.convert.brokerage.record;
  1 +package cn.iocoder.yudao.module.trade.convert.brokerage;
2 2  
  3 +import cn.hutool.core.math.Money;
3 4 import cn.hutool.core.util.ObjectUtil;
4 5 import cn.hutool.core.util.StrUtil;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
6 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO;
8   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO;
9   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  9 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
  10 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordRespVO;
  11 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
  12 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
  13 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
  14 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
  15 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
10 16 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
11 17 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
12 18 import org.mapstruct.Mapper;
  19 +import org.mapstruct.MappingTarget;
13 20 import org.mapstruct.factory.Mappers;
14 21  
15 22 import java.time.LocalDateTime;
... ... @@ -45,7 +52,7 @@ public interface BrokerageRecordConvert {
45 52 .setBizType(bizType.getType()).setBizId(bizId)
46 53 .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice())
47 54 .setTitle(title)
48   - .setDescription(StrUtil.format(bizType.getDescription(), String.format("¥%.2f", brokeragePrice / 100d)))
  55 + .setDescription(StrUtil.format(bizType.getDescription(), MoneyUtils.fenToYuanStr(Math.abs(brokeragePrice))))
49 56 .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime)
50 57 .setSourceUserLevel(sourceUserLevel).setSourceUserId(sourceUserId);
51 58 }
... ... @@ -60,4 +67,17 @@ public interface BrokerageRecordConvert {
60 67 }
61 68 return result;
62 69 }
  70 +
  71 + BrokerageRecordPageReqVO convert(AppBrokerageRecordPageReqVO pageReqVO, Long userId);
  72 +
  73 + PageResult<AppBrokerageRecordRespVO> convertPage02(PageResult<BrokerageRecordDO> pageResult);
  74 +
  75 + default PageResult<AppBrokerageUserRankByPriceRespVO> convertPage03(PageResult<AppBrokerageUserRankByPriceRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
  76 + for (AppBrokerageUserRankByPriceRespVO vo : pageResult.getList()) {
  77 + copyTo(userMap.get(vo.getId()), vo);
  78 + }
  79 + return pageResult;
  80 + }
  81 +
  82 + void copyTo(MemberUserRespDTO from, @MappingTarget AppBrokerageUserRankByPriceRespVO to);
63 83 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageUserConvert.java
1   -package cn.iocoder.yudao.module.trade.convert.brokerage.user;
  1 +package cn.iocoder.yudao.module.trade.convert.brokerage;
2 2  
3 3 import cn.hutool.core.map.MapUtil;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
6   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserRespVO;
7   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  6 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserRespVO;
  7 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
  8 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
8 9 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
  10 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
9 11 import org.mapstruct.Mapper;
  12 +import org.mapstruct.MappingTarget;
10 13 import org.mapstruct.factory.Mappers;
11 14  
12 15 import java.util.List;
... ... @@ -27,13 +30,14 @@ public interface BrokerageUserConvert {
27 30  
28 31 List<BrokerageUserRespVO> convertList(List<BrokerageUserDO> list);
29 32  
30   - PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> page);
  33 + PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> page, Map<Long, MemberUserRespDTO> userMap, Map<Long, Long> brokerageUserCountMap, Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap);
31 34  
32 35 default PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> pageResult,
33 36 Map<Long, MemberUserRespDTO> userMap,
34 37 Map<Long, Long> brokerageUserCountMap,
35   - Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap) {
36   - PageResult<BrokerageUserRespVO> result = convertPage(pageResult);
  38 + Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap,
  39 + Map<Long, UserWithdrawSummaryBO> withdrawMap) {
  40 + PageResult<BrokerageUserRespVO> result = convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap);
37 41 for (BrokerageUserRespVO userVO : result.getList()) {
38 42 // 用户信息
39 43 copyTo(userMap.get(userVO.getId()), userVO);
... ... @@ -44,7 +48,10 @@ public interface BrokerageUserConvert {
44 48 Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(userVO.getId()));
45 49 userVO.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0))
46 50 .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));
47   - // todo 已提现次数、已提现金额
  51 + // 已提现次数、已提现金额
  52 + Optional<UserWithdrawSummaryBO> withdrawSummaryOptional = Optional.ofNullable(withdrawMap.get(userVO.getId()));
  53 + userVO.setWithdrawCount(withdrawSummaryOptional.map(UserWithdrawSummaryBO::getCount).orElse(0))
  54 + .setWithdrawPrice(withdrawSummaryOptional.map(UserWithdrawSummaryBO::getPrice).orElse(0));
48 55 userVO.setWithdrawCount(0).setWithdrawPrice(0);
49 56 }
50 57 return result;
... ... @@ -55,4 +62,13 @@ public interface BrokerageUserConvert {
55 62 user -> target.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
56 63 return target;
57 64 }
  65 +
  66 + default PageResult<AppBrokerageUserRankByUserCountRespVO> convertPage03(PageResult<AppBrokerageUserRankByUserCountRespVO> pageResult,
  67 + Map<Long, MemberUserRespDTO> userMap) {
  68 + pageResult.getList().forEach(vo -> copyTo(userMap.get(vo.getId()), vo));
  69 + return pageResult;
  70 + }
  71 +
  72 + void copyTo(MemberUserRespDTO from, @MappingTarget AppBrokerageUserRankByUserCountRespVO to);
  73 +
58 74 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/withdraw/BrokerageWithdrawConvert.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageWithdrawConvert.java
1   -package cn.iocoder.yudao.module.trade.convert.brokerage.withdraw;
  1 +package cn.iocoder.yudao.module.trade.convert.brokerage;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
4 5 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRejectReqVO;
6   -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.withdraw.vo.BrokerageWithdrawRespVO;
7   -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.withdraw.BrokerageWithdrawDO;
  6 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
  7 +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
  8 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
  9 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
  10 +import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
  11 +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
  12 +import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
8 13 import org.mapstruct.Mapper;
9 14 import org.mapstruct.factory.Mappers;
10 15  
... ... @@ -22,7 +27,7 @@ public interface BrokerageWithdrawConvert {
22 27  
23 28 BrokerageWithdrawConvert INSTANCE = Mappers.getMapper(BrokerageWithdrawConvert.class);
24 29  
25   - BrokerageWithdrawDO convert(BrokerageWithdrawRejectReqVO bean);
  30 + BrokerageWithdrawDO convert(AppBrokerageWithdrawCreateReqVO createReqVO, Long userId, Integer feePrice);
26 31  
27 32 BrokerageWithdrawRespVO convert(BrokerageWithdrawDO bean);
28 33  
... ... @@ -38,4 +43,15 @@ public interface BrokerageWithdrawConvert {
38 43 return result;
39 44 }
40 45  
  46 + PageResult<AppBrokerageWithdrawRespVO> convertPage02(PageResult<BrokerageWithdrawDO> pageResult);
  47 +
  48 + default PageResult<AppBrokerageWithdrawRespVO> convertPage03(PageResult<BrokerageWithdrawDO> pageResult) {
  49 + PageResult<AppBrokerageWithdrawRespVO> result = convertPage02(pageResult);
  50 + for (AppBrokerageWithdrawRespVO vo : result.getList()) {
  51 + vo.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_STATUS, vo.getStatus()));
  52 + }
  53 + return result;
  54 + }
  55 +
  56 + BrokerageWithdrawPageReqVO convert(AppBrokerageWithdrawPageReqVO pageReqVO, Long userId);
41 57 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/config/TradeConfigConvert.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.convert.config;
2 2  
3 3 import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigRespVO;
4 4 import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO;
  5 +import cn.iocoder.yudao.module.trade.controller.app.config.vo.AppTradeConfigRespVO;
5 6 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
6 7 import org.mapstruct.Mapper;
7 8 import org.mapstruct.factory.Mappers;
... ... @@ -20,4 +21,5 @@ public interface TradeConfigConvert {
20 21  
21 22 TradeConfigRespVO convert(TradeConfigDO bean);
22 23  
  24 + AppTradeConfigRespVO convert02(TradeConfigDO tradeConfig);
23 25 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
1 1 package cn.iocoder.yudao.module.trade.convert.order;
2 2  
  3 +import cn.hutool.core.util.BooleanUtil;
3 4 import cn.hutool.core.util.StrUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
... ... @@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
14 15 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
15 16 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
16 17 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
  18 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
17 19 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
18 20 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
19 21 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
... ... @@ -56,6 +58,7 @@ public interface TradeOrderConvert {
56 58  
57 59 @Mappings({
58 60 @Mapping(target = "id", ignore = true),
  61 + @Mapping(source = "userId", target = "userId"),
59 62 @Mapping(source = "createReqVO.couponId", target = "couponId"),
60 63 @Mapping(target = "remark", ignore = true),
61 64 @Mapping(source = "createReqVO.remark", target = "userRemark"),
... ... @@ -64,14 +67,11 @@ public interface TradeOrderConvert {
64 67 @Mapping(source = "calculateRespBO.price.deliveryPrice", target = "deliveryPrice"),
65 68 @Mapping(source = "calculateRespBO.price.couponPrice", target = "couponPrice"),
66 69 @Mapping(source = "calculateRespBO.price.pointPrice", target = "pointPrice"),
67   - @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice"),
68   - @Mapping(source = "address.name", target = "receiverName"),
69   - @Mapping(source = "address.mobile", target = "receiverMobile"),
70   - @Mapping(source = "address.areaId", target = "receiverAreaId"),
71   - @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"),
  70 + @Mapping(source = "calculateRespBO.price.vipPrice", target = "vipPrice"),
  71 + @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice")
72 72 })
73 73 TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO,
74   - TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address);
  74 + TradePriceCalculateRespBO calculateRespBO);
75 75  
76 76 TradeOrderRespDTO convert(TradeOrderDO orderDO);
77 77  
... ... @@ -89,23 +89,16 @@ public interface TradeOrderConvert {
89 89 TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item);
90 90  
91 91 default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
92   - return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list));
  92 + List<ProductSkuUpdateStockReqDTO.Item> items = CollectionUtils.convertList(list, item ->
  93 + new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount()));
  94 + return new ProductSkuUpdateStockReqDTO(items);
93 95 }
94   -
95   - default ProductSkuUpdateStockReqDTO convertNegative(List<TradeOrderItemDO> list) {
96   - List<ProductSkuUpdateStockReqDTO.Item> items = TradeOrderConvert.INSTANCE.convertList(list);
97   - items.forEach(item -> item.setIncrCount(-item.getIncrCount()));
  96 + default ProductSkuUpdateStockReqDTO convertNegative(List<AppTradeOrderSettlementReqVO.Item> list) {
  97 + List<ProductSkuUpdateStockReqDTO.Item> items = CollectionUtils.convertList(list, item ->
  98 + new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount()));
98 99 return new ProductSkuUpdateStockReqDTO(items);
99 100 }
100 101  
101   - List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
102   -
103   - @Mappings({
104   - @Mapping(source = "skuId", target = "id"),
105   - @Mapping(source = "count", target = "incrCount"),
106   - })
107   - ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean);
108   -
109 102 default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
110 103 TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) {
111 104 PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO()
... ... @@ -220,7 +213,11 @@ public interface TradeOrderConvert {
220 213  
221 214 default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
222 215 List<CartDO> cartList) {
223   - TradePriceCalculateReqBO reqBO = convert(settlementReqVO).setUserId(userId).setItems(new ArrayList<>(settlementReqVO.getItems().size()));
  216 + TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO().setUserId(userId)
  217 + .setCouponId(settlementReqVO.getCouponId()).setPointStatus(settlementReqVO.getPointStatus())
  218 + .setDeliveryType(settlementReqVO.getDeliveryType()).setAddressId(settlementReqVO.getAddressId())
  219 + .setPickUpStoreId(settlementReqVO.getPickUpStoreId())
  220 + .setItems(new ArrayList<>(settlementReqVO.getItems().size()));
224 221 // 商品项的构建
225 222 Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
226 223 for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {
... ... @@ -273,11 +270,16 @@ public interface TradeOrderConvert {
273 270  
274 271 TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);
275 272  
276   - default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item, ProductSkuRespDTO sku) {
277   - return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
  273 + default BrokerageAddReqBO convert(MemberUserRespDTO user, TradeOrderItemDO item,
  274 + ProductSpuRespDTO spu, ProductSkuRespDTO sku) {
  275 + BrokerageAddReqBO bo = new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
278 276 .setBasePrice(item.getPayPrice() * item.getCount())
279 277 .setTitle(StrUtil.format("{}成功购买{}", user.getNickname(), item.getSpuName()))
280   - .setFirstFixedPrice(sku.getFirstBrokeragePrice()).setSecondFixedPrice(sku.getSecondBrokeragePrice());
  278 + .setFirstFixedPrice(0).setSecondFixedPrice(0);
  279 + if (BooleanUtil.isTrue(spu.getSubCommissionType())) {
  280 + bo.setFirstFixedPrice(sku.getFirstBrokeragePrice()).setSecondFixedPrice(sku.getSecondBrokeragePrice());
  281 + }
  282 + return bo;
281 283 }
282 284  
283 285 TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageRecordDO.java
1   -package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record;
  1 +package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
... ...