diff --git a/sql/mysql/brokerage.sql b/sql/mysql/brokerage.sql index 127fcb728..a84d80051 100644 --- a/sql/mysql/brokerage.sql +++ b/sql/mysql/brokerage.sql @@ -3,8 +3,8 @@ create table trade_config ( id bigint auto_increment comment '自增主键' primary key, brokerage_enabled bit default 1 not null comment '是否启用分佣', - brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:0-人人分销 1-指定分销', - brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 0-没有推广人,1-新用户', + brokerage_enabled_condition tinyint default 0 not null comment '分佣模式:1-人人分销 2-指定分销', + brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模式: 1-没有推广人,2-新用户, 3-扫码覆盖', brokerage_post_urls varchar(2000) default '' null comment '分销海报图地址数组', brokerage_first_percent int default 0 not null comment '一级返佣比例', brokerage_second_percent int default 0 not null comment '二级返佣比例', @@ -23,22 +23,22 @@ create table trade_config -- 增加分销用户扩展表 create table trade_brokerage_user ( - id bigint auto_increment comment '用户编号' primary key, - brokerage_user_id bigint not null comment '推广员编号', - brokerage_bind_time datetime null comment '推广员绑定时间', - brokerage_enabled bit default 1 not null comment '是否成为推广员', - brokerage_time datetime null comment '成为分销员时间', - brokerage_price int default 0 not null comment '可用佣金', - frozen_brokerage_price int default 0 not null comment '冻结佣金', - creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', - updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', - deleted bit default b'0' not null comment '是否删除', - tenant_id bigint default 0 not null comment '租户编号' + id bigint auto_increment comment '用户编号' primary key, + bind_user_id bigint null comment '推广员编号', + bind_user_time datetime null comment '推广员绑定时间', + brokerage_enabled bit default 1 not null comment '是否成为推广员', + brokerage_time datetime null comment '成为分销员时间', + price int default 0 not null comment '可用佣金', + frozen_price int default 0 not null comment '冻结佣金', + creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者', + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者', + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + deleted bit default b'0' not null comment '是否删除', + tenant_id bigint default 0 not null comment '租户编号' ) comment '分销用户'; -create index idx_invite_user_id on trade_brokerage_user (brokerage_user_id) comment '推广员编号'; +create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编号'; create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是否成为推广员'; @@ -104,14 +104,15 @@ create index idx_audit_status on trade_brokerage_withdraw (status) comment '状 insert into system_dict_type(type, name) values ('brokerage_enabled_condition', '分佣模式'); insert into system_dict_data(dict_type, label, value, sort, remark) -values ('brokerage_enabled_condition', '人人分销', 0, 0, '所有用户都可以分销'), - ('brokerage_enabled_condition', '指定分销', 1, 1, '仅可后台手动设置推广员'); +values ('brokerage_enabled_condition', '人人分销', 1, 1, '所有用户都可以分销'), + ('brokerage_enabled_condition', '指定分销', 2, 2, '仅可后台手动设置推广员'); insert into system_dict_type(type, name) values ('brokerage_bind_mode', '分销关系绑定模式'); insert into system_dict_data(dict_type, label, value, sort, remark) -values ('brokerage_bind_mode', '没有推广人', 0, 0, '只要用户没有推广人,随时都可以绑定推广关系'), - ('brokerage_bind_mode', '新用户', 1, 1, '仅新用户注册时才能绑定推广关系'); +values ('brokerage_bind_mode', '没有推广人', 1, 1, '只要用户没有推广人,随时都可以绑定推广关系'), + ('brokerage_bind_mode', '新用户', 2, 2, '仅新用户注册时才能绑定推广关系'), + ('brokerage_bind_mode', '扫码覆盖', 3, 3, '如果用户已经有推广人,推广人会被变更'); insert into system_dict_type(type, name) values ('brokerage_withdraw_type', '佣金提现类型'); @@ -124,8 +125,8 @@ values ('brokerage_withdraw_type', '钱包', 1, 1), insert into system_dict_type(type, name) values ('brokerage_record_biz_type', '佣金记录业务类型'); insert into system_dict_data(dict_type, label, value, sort) -values ('brokerage_record_biz_type', '订单返佣', 0, 0), - ('brokerage_record_biz_type', '申请提现', 1, 1); +values ('brokerage_record_biz_type', '订单返佣', 1, 1), + ('brokerage_record_biz_type', '申请提现', 2, 2); insert into system_dict_type(type, name) values ('brokerage_record_status', '佣金记录状态'); @@ -185,12 +186,15 @@ SELECT @parentId := LAST_INSERT_ID(); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('分销用户查询', 'trade:brokerage-user:query', 3, 1, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 2, @parentId, '', '', '', 0); +VALUES ('分销用户推广人查询', 'trade:brokerage-user:user-query', 3, 2, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 3, @parentId, '', '', '', 0); +VALUES ('分销用户推广订单查询', 'trade:brokerage-user:order-query', 3, 3, @parentId, '', '', '', 0); INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0); - +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 5, @parentId, '', '', '', 0); +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) +VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 6, @parentId, '', '', '', 0); -- 增加菜单:佣金记录 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java similarity index 71% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java rename to yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index 5e5d859e6..e2fd3fa6e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/util/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.pay.util; +package cn.iocoder.yudao.framework.common.util.number; import cn.hutool.core.util.NumberUtil; @@ -23,6 +23,17 @@ public class MoneyUtils { return calculateRatePrice(price, rate, 0, RoundingMode.HALF_UP).intValue(); } + /** + * 计算百分比金额,向下传入 + * + * @param price 金额 + * @param rate 百分比,例如说 56.77% 则传入 56.77 + * @return 百分比金额 + */ + public static Integer calculateRatePriceFloor(Integer price, Double rate) { + return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue(); + } + /** * 计算百分比金额 * diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java new file mode 100644 index 000000000..4d7314d4b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.trade.api.brokerage; + +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; + +/** + * 分销 API 接口 + * + * @author owen + */ +public interface BrokerageApi { + + /** + * 获得分销用户 + * + * @param userId 用户编号 + * @return 分销用户信息 + */ + BrokerageUserDTO getBrokerageUser(Long userId); + + /** + * 绑定推广员 + * + * @param userId 用户编号 + * @param bindUserId 推广员编号 + * @param isNewUser 是否为新用户 + * @return 是否绑定 + */ + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java new file mode 100644 index 000000000..864abe148 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/dto/BrokerageUserDTO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.trade.api.brokerage.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 分销用户 DTO + * + * @author owen + */ +@Data +public class BrokerageUserDTO { + + /** + * 用户编号 + *

+ * 对应 MemberUserDO 的 id 字段 + */ + private Long id; + + /** + * 推广员编号 + *

+ * 关联 MemberUserDO 的 id 字段 + */ + private Long bindUserId; + /** + * 推广员绑定时间 + */ + private LocalDateTime bindUserTime; + + /** + * 推广资格 + */ + private Boolean brokerageEnabled; + /** + * 成为分销员时间 + */ + private LocalDateTime brokerageTime; + + /** + * 可用佣金 + */ + private Integer price; + /** + * 冻结佣金 + */ + private Integer frozenPrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index f6c0ca782..236e7af23 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -77,5 +77,12 @@ public interface ErrorCodeConstants { // ========== 分销用户 模块 1011007000 ========== ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在"); + ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足"); + ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己"); + ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格"); + ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员"); + ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定"); + ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人"); + ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级"); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java index 19bb53daa..3b6610ac9 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageBindModeEnum.java @@ -15,16 +15,18 @@ import java.util.Arrays; @Getter public enum BrokerageBindModeEnum implements IntArrayValuable { - // TODO @疯狂:要不从 1 开始? /** * 只要用户没有推广人,随时都可以绑定分销关系 */ - ANYTIME(0, "没有推广人"), + ANYTIME(1, "没有推广人"), /** * 仅新用户注册时才能绑定推广关系 */ - REGISTER(1, "新用户"), - // TODO @疯狂:要加个 2,每次扫码都覆盖 + REGISTER(2, "新用户"), + /** + * 每次扫码都覆盖 + */ + OVERRIDE(3, "扫码覆盖"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java index 1d1ef0c81..990d10e16 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageEnabledConditionEnum.java @@ -15,15 +15,14 @@ import java.util.Arrays; @Getter public enum BrokerageEnabledConditionEnum implements IntArrayValuable { - // TODO @疯狂:这个也从 1 开始哇 /** * 所有用户都可以分销 */ - ALL(0, "人人分销"), + ALL(1, "人人分销"), /** * 仅可后台手动设置推广员 */ - ADMIN(1, "指定分销"), + ADMIN(2, "指定分销"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageEnabledConditionEnum::getCondition).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java index 50c83c05a..ae798a6ac 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageRecordBizTypeEnum.java @@ -15,9 +15,8 @@ import java.util.Arrays; @Getter public enum BrokerageRecordBizTypeEnum implements IntArrayValuable { - // TODO @疯狂:这个也从 1 开始哇 - ORDER(0, "获得推广佣金", "获得推广佣金 {}", true), - WITHDRAW(1, "提现申请", "提现申请扣除佣金 {}", false), + ORDER(1, "获得推广佣金", "获得推广佣金 {}", true), + WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java new file mode 100644 index 000000000..4a534fa22 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.trade.api.brokerage; + +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; +import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 分销 API 接口实现类 + * + * @author owen + */ +@Service +@Validated +public class BrokerageApiImpl implements BrokerageApi { + + @Resource + private BrokerageUserService brokerageUserService; + + public BrokerageUserDTO getBrokerageUser(Long userId) { + return BrokerageUserConvert.INSTANCE.convertDTO(brokerageUserService.getBrokerageUser(userId)); + } + + @Override + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + return brokerageUserService.bindUser(userId, bindUserId, isNewUser); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java similarity index 59% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java index 38b2f4d71..81034124b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/TradeBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -26,26 +26,26 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @RestController @RequestMapping("/trade/brokerage-record") @Validated -public class TradeBrokerageRecordController { +public class BrokerageRecordController { @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @GetMapping("/get") @Operation(summary = "获得佣金记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") - public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { - TradeBrokerageRecordDO tradeBrokerageRecord = tradeBrokerageRecordService.getBrokerageRecord(id); - return success(TradeBrokerageRecordConvert.INSTANCE.convert(tradeBrokerageRecord)); + public CommonResult getBrokerageRecord(@RequestParam("id") Integer id) { + BrokerageRecordDO brokerageRecord = brokerageRecordService.getBrokerageRecord(id); + return success(BrokerageRecordConvert.INSTANCE.convert(brokerageRecord)); } @GetMapping("/page") @Operation(summary = "获得佣金记录分页") @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") - public CommonResult> getBrokerageRecordPage(@Valid TradeBrokerageRecordPageReqVO pageVO) { - PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(pageVO); - return success(TradeBrokerageRecordConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) { + PageResult pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO); + return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java index f15d07706..cce84a804 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class TradeBrokerageRecordBaseVO { +public class BrokerageRecordBaseVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java similarity index 94% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java index abd948f09..533fbd2ca 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageRecordPageReqVO extends PageParam { +public class BrokerageRecordPageReqVO extends PageParam { @Schema(description = "用户编号", example = "25973") private Long userId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java similarity index 89% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java index 724d7d3e5..aead00a08 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/TradeBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java @@ -11,7 +11,7 @@ import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageRecordRespVO extends TradeBrokerageRecordBaseVO { +public class BrokerageRecordRespVO extends BrokerageRecordBaseVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896") private Integer id; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java new file mode 100644 index 000000000..f29e2c9a8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*; +import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Map; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - 分销用户") +@RestController +@RequestMapping("/trade/brokerage-user") +@Validated +public class BrokerageUserController { + + @Resource + private BrokerageUserService brokerageUserService; + @Resource + private BrokerageRecordService brokerageRecordService; + + @Resource + private MemberUserApi memberUserApi; + + @PutMapping("/update-brokerage-user") + @Operation(summary = "修改推广员") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')") + public CommonResult updateBrokerageUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) { + brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId()); + return success(true); + } + + @PutMapping("/clear-brokerage-user") + @Operation(summary = "清除推广员") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-brokerage-user')") + public CommonResult clearBrokerageUser(@Valid @RequestBody BrokerageUserClearBrokerageUserReqVO updateReqVO) { + brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null); + return success(true); + } + + @PutMapping("/update-brokerage-enable") + @Operation(summary = "修改推广资格") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") + public CommonResult updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { + brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getEnabled()); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得分销用户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") + public CommonResult getBrokerageUser(@RequestParam("id") Long id) { + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); + return success(BrokerageUserConvert.INSTANCE.convert(brokerageUser)); + } + + @GetMapping("/page") + @Operation(summary = "获得分销用户分页") + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") + public CommonResult> getBrokerageUserPage(@Valid BrokerageUserPageReqVO pageVO) { + // 分页查询 + PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); + + // 涉及到的用户 + Set userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId); + // 查询用户信息 + Map userMap = memberUserApi.getUserMap(userIds); + // 合计分佣订单 + Map userOrderSummaryMap = convertMap(userIds, + userId -> userId, + userId -> brokerageRecordService.summaryByUserIdAndBizTypeAndStatus(userId, + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus())); + // 合计推广用户数量 + Map brokerageUserCountMap = convertMap(userIds, + userId -> userId, + userId -> brokerageUserService.getCountByBindUserId(userId)); + + // todo 合计提现 + + return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java deleted file mode 100644 index e4cc63fb9..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/TradeBrokerageUserController.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.*; -import cn.iocoder.yudao.module.trade.convert.brokerage.user.TradeBrokerageUserConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.validation.Valid; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - 分销用户") -@RestController -@RequestMapping("/trade/brokerage-user") -@Validated -public class TradeBrokerageUserController { - - @Resource - private TradeBrokerageUserService brokerageUserService; - - @PutMapping("/update-brokerage-user") - @Operation(summary = "修改推广员") - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')") - public CommonResult updateBrokerageUser(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageUserReqVO updateReqVO) { - brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBrokerageUserId()); - return success(true); - } - - @PutMapping("/clear-brokerage-user") - @Operation(summary = "清除推广员") - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-brokerage-user')") - public CommonResult clearBrokerageUser(@Valid @RequestBody TradeBrokerageUserClearBrokerageUserReqVO updateReqVO) { - brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null); - return success(true); - } - - @PutMapping("/update-brokerage-enable") - @Operation(summary = "修改推广资格") - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-enable')") - public CommonResult updateBrokerageEnabled(@Valid @RequestBody TradeBrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) { - brokerageUserService.updateBrokerageEnabled(updateReqVO.getId(), updateReqVO.getBrokerageEnabled()); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得分销用户") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") - public CommonResult getBrokerageUser(@RequestParam("id") Long id) { - TradeBrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); - return success(TradeBrokerageUserConvert.INSTANCE.convert(brokerageUser)); - } - - @GetMapping("/page") - @Operation(summary = "获得分销用户分页") - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") - public CommonResult> getBrokerageUserPage(@Valid TradeBrokerageUserPageReqVO pageVO) { - PageResult pageResult = brokerageUserService.getBrokerageUserPage(pageVO); - return success(TradeBrokerageUserConvert.INSTANCE.convertPage(pageResult)); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java similarity index 88% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java index d75e6a1b1..34f792b72 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserBaseVO.java @@ -14,15 +14,15 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data -public class TradeBrokerageUserBaseVO { +public class BrokerageUserBaseVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") @NotNull(message = "推广员编号不能为空") - private Long brokerageUserId; + private Long bindUserId; @Schema(description = "推广员绑定时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime brokerageBindTime; + private LocalDateTime bindUserTime; @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "推广资格不能为空") @@ -34,10 +34,10 @@ public class TradeBrokerageUserBaseVO { @Schema(description = "可用佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "11089") @NotNull(message = "可用佣金不能为空") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "30916") @NotNull(message = "冻结佣金不能为空") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java similarity index 90% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java index 18a5a5e85..edb0102a0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserClearBrokerageUserReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserClearBrokerageUserReqVO.java @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserClearBrokerageUserReqVO { +public class BrokerageUserClearBrokerageUserReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java similarity index 90% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java index ec63775d3..e6908e8aa 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java @@ -15,10 +15,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TradeBrokerageUserPageReqVO extends PageParam { +public class BrokerageUserPageReqVO extends PageParam { @Schema(description = "推广员编号", example = "4587") - private Long brokerageUserId; + private Long bindUserId; @Schema(description = "推广资格") private Boolean brokerageEnabled; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java new file mode 100644 index 000000000..c353b4614 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 分销用户 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BrokerageUserRespVO extends BrokerageUserBaseVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + + // ========== 用户信息 ========== + + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; + @Schema(description = "用户昵称", example = "李四") + private String nickname; + + + // ========== 推广信息 ========== + + @Schema(description = "推广用户数量(一级)", example = "20019") + private Integer brokerageUserCount; + @Schema(description = "推广订单数量", example = "20019") + private Integer brokerageOrderCount; + @Schema(description = "推广订单金额", example = "20019") + private Integer brokerageOrderPrice; + + + // ========== 提现信息 ========== + + @Schema(description = "已提现金额", example = "20019") + private Integer withdrawPrice; + @Schema(description = "已提现次数", example = "20019") + private Integer withdrawCount; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java similarity index 79% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java index 1fd38b028..92001e698 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageEnabledReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageEnabledReqVO.java @@ -9,16 +9,14 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserUpdateBrokerageEnabledReqVO { +public class BrokerageUserUpdateBrokerageEnabledReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") private Long id; - // TODO @疯狂:是不是这个字段,可以改成 enabled - @Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "推广资格不能为空") - private Boolean brokerageEnabled; + private Boolean enabled; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java similarity index 88% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java index 28ea301c1..d62c7fd1e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserUpdateBrokerageUserReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserUpdateBrokerageUserReqVO.java @@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO") @Data @ToString(callSuper = true) -public class TradeBrokerageUserUpdateBrokerageUserReqVO { +public class BrokerageUserUpdateBrokerageUserReqVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") @NotNull(message = "用户编号不能为空") @@ -17,6 +17,6 @@ public class TradeBrokerageUserUpdateBrokerageUserReqVO { @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587") @NotNull(message = "推广员编号不能为空") - private Long brokerageUserId; + private Long bindUserId; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java deleted file mode 100644 index 090eb04b5..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/TradeBrokerageUserRespVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 分销用户 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TradeBrokerageUserRespVO extends TradeBrokerageUserBaseVO { - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019") - private Long id; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java index 55b168582..ee20156f1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/config/vo/TradeConfigBaseVO.java @@ -54,7 +54,6 @@ public class TradeConfigBaseVO { @PositiveOrZero(message = "用户提现最低金额不能是负数") private Integer brokerageWithdrawMinPrice; - // TODO @疯狂:要不要做成字典?按道理都可以体现对哇?感觉是全局的配置哈; @Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]") @NotEmpty(message = "提现银行不能为空") private List brokerageBankNames; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java index 1b760be05..ef1634098 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java @@ -4,21 +4,22 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.validation.Valid; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static java.util.Arrays.asList; @Tag(name = "用户 APP - 分销用户") @@ -27,6 +28,8 @@ import static java.util.Arrays.asList; @Validated @Slf4j public class AppBrokerageUserController { + @Resource + private BrokerageUserService brokerageUserService; // TODO 芋艿:临时 mock => @GetMapping("/get") @@ -34,8 +37,8 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUser() { AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO() - .setBrokeragePrice(2000) - .setFrozenBrokeragePrice(3000); + .setPrice(2000) + .setFrozenPrice(3000); return success(respVO); } @@ -45,10 +48,10 @@ public class AppBrokerageUserController { @PreAuthenticated public CommonResult getBrokerageUserSummary() { AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO() - .setYesterdayBrokeragePrice(1) - .setBrokeragePrice(2) - .setFrozenBrokeragePrice(3) - .setWithdrawBrokeragePrice(4) + .setYesterdayPrice(1) + .setPrice(2) + .setFrozenPrice(3) + .setWithdrawPrice(4) .setFirstBrokerageUserCount(166) .setSecondBrokerageUserCount(233); return success(respVO); @@ -81,16 +84,16 @@ public class AppBrokerageUserController { public CommonResult> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) { AppBrokerageUserRankByPriceRespVO vo1 = new AppBrokerageUserRankByPriceRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(10); + .setPrice(10); AppBrokerageUserRankByPriceRespVO vo2 = new AppBrokerageUserRankByPriceRespVO() .setId(2L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(6); + .setPrice(6); AppBrokerageUserRankByPriceRespVO vo3 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(4); + .setPrice(4); AppBrokerageUserRankByPriceRespVO vo4 = new AppBrokerageUserRankByPriceRespVO() .setId(3L).setNickname("芋3**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(4); + .setPrice(4); return success(new PageResult<>(asList(vo1, vo2, vo3, vo4), 10L)); } @@ -102,11 +105,11 @@ public class AppBrokerageUserController { AppBrokerageUserChildSummaryPageReqVO pageReqVO) { AppBrokerageUserChildSummaryRespVO vo1 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋1**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(10).setBrokeragePrice(20).setBrokerageOrderCount(30) + .setPrice(10).setPrice(20).setBrokerageOrderCount(30) .setBrokerageTime(LocalDateTime.now()); AppBrokerageUserChildSummaryRespVO vo2 = new AppBrokerageUserChildSummaryRespVO() .setId(1L).setNickname("芋2**艿").setAvatar("http://www.iocoder.cn/images/common/wechat_mp_2017_07_31_bak.jpg") - .setBrokeragePrice(20).setBrokeragePrice(30).setBrokerageOrderCount(40) + .setPrice(20).setPrice(30).setBrokerageOrderCount(40) .setBrokerageTime(LocalDateTime.now()); return success(new PageResult<>(asList(vo1, vo2), 10L)); } @@ -120,4 +123,10 @@ public class AppBrokerageUserController { return success(1); } + @PutMapping("/bind-user") + @Operation(summary = "绑定推广员") + public CommonResult getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) { + return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false)); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java index b7675e6ec..e2df6dae6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -8,12 +11,12 @@ import lombok.Data; @Data public class AppBrokerageRecordPageReqVO extends PageParam { - // TODO @疯狂:要加下枚举校验 - @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}") private Integer bizType; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageRecordStatusEnum.class, message = "状态必须是 {value}") private Integer status; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java new file mode 100644 index 000000000..f2a14996a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "应用 App - 绑定推广员 Request VO") +@Data +public class AppBrokerageUserBindReqVO extends PageParam { + + @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "推广员编号不能为空") + private Long bindUserId; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java index 1beb1b5e2..55d88d74f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserChildSummaryRespVO.java @@ -19,7 +19,7 @@ public class AppBrokerageUserChildSummaryRespVO { private String avatar; @Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer brokeragePrice; + private Integer price; @Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer brokerageOrderCount; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java index 64fafe329..33a089cc6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java @@ -8,16 +8,16 @@ import lombok.Data; public class AppBrokerageUserMySummaryRespVO { @Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer yesterdayBrokeragePrice; + private Integer yesterdayPrice; @Schema(description = "提现的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer withdrawBrokeragePrice; + private Integer withdrawPrice; @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer firstBrokerageUserCount; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java index 91345ea78..d80fb67a2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRankByPriceRespVO.java @@ -17,6 +17,6 @@ public class AppBrokerageUserRankByPriceRespVO { private String avatar; @Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer brokeragePrice; + private Integer price; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java index 04f1a7278..9db6e0cc2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserRespVO.java @@ -8,9 +8,9 @@ import lombok.Data; public class AppBrokerageUserRespVO { @Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408") - private Integer brokeragePrice; + private Integer price; @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java index 75aec997b..752818130 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java @@ -1,29 +1,76 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw; +import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.URL; +import javax.validation.Validator; import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; @Schema(description = "用户 App - 分销提现创建 Request VO") @Data public class AppBrokerageWithdrawCreateReqVO { - // TODO @疯狂:参数校验逻辑,需要根据 type 进行不同的校验;感觉可以通过分组? - @Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}") private Integer type; - @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") // 银行卡号/微信账号/支付宝账号 + @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @Min(value = 1, message = "提现金额不能小于 1") + private Integer price; + + + // ========== 银行卡、微信、支付宝 提现相关字段 ========== + + @Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789") + @NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class}) private String accountNo; + + // ========== 微信、支付宝 提现相关字段 ========== + @Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png") @URL(message = "收款码的图片,必须是一个 URL") private String accountQrCodeUrl; - @Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") - @Min(value = 1, message = "提现金额必须大于 1") - private Integer price; + + // ========== 银行卡 提现相关字段 ========== + + @Schema(description = "持卡人姓名", example = "张三") + @NotBlank(message = "持卡人姓名不能为空", groups = {Bank.class}) + private String name; + @Schema(description = "提现银行", example = "1") + @NotBlank(message = "提现银行不能为空", groups = {Bank.class}) + private Integer bankName; + @Schema(description = "开户地址", example = "海淀支行") + private String bankAddress; + + public interface Wallet { + } + + public interface Bank { + } + + public interface Wechat { + } + + public interface Alipay { + } + + public void validate(Validator validator) { + if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(type)) { + ValidationUtils.validate(validator, this, Wallet.class); + } else if (BrokerageWithdrawTypeEnum.BANK.getType().equals(type)) { + ValidationUtils.validate(validator, this, Bank.class); + } else if (BrokerageWithdrawTypeEnum.WECHAT.getType().equals(type)) { + ValidationUtils.validate(validator, this, Wechat.class); + } else if (BrokerageWithdrawTypeEnum.ALIPAY.getType().equals(type)) { + ValidationUtils.validate(validator, this, Alipay.class); + } + } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java similarity index 51% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java index 1e8290460..9307a4f55 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/TradeBrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import org.mapstruct.Mapper; @@ -19,29 +20,32 @@ import java.util.List; * @author owen */ @Mapper -public interface TradeBrokerageRecordConvert { +public interface BrokerageRecordConvert { - TradeBrokerageRecordConvert INSTANCE = Mappers.getMapper(TradeBrokerageRecordConvert.class); + BrokerageRecordConvert INSTANCE = Mappers.getMapper(BrokerageRecordConvert.class); - TradeBrokerageRecordRespVO convert(TradeBrokerageRecordDO bean); + BrokerageRecordRespVO convert(BrokerageRecordDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - default TradeBrokerageRecordDO convert(TradeBrokerageUserDO user, String bizId, int brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime) { + default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, + Integer brokerageFrozenDays, int brokerage, LocalDateTime unfreezeTime, + String title) { + brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); // 不冻结时,佣金直接就是结算状态 Integer status = brokerageFrozenDays > 0 ? BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus() : BrokerageRecordStatusEnum.SETTLEMENT.getStatus(); - return new TradeBrokerageRecordDO() + return new BrokerageRecordDO() .setUserId(user.getId()) - .setBizType(BrokerageRecordBizTypeEnum.ORDER.getType()) + .setBizType(bizType.getType()) .setBizId(bizId) .setPrice(brokerage) - .setTotalPrice(user.getBrokeragePrice()) - .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》 - .setDescription(StrUtil.format(BrokerageRecordBizTypeEnum.ORDER.getDescription(), String.valueOf(brokerage / 100.0))) + .setTotalPrice(user.getPrice()) + .setTitle(title) + .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokerage / 100.0))) .setStatus(status) .setFrozenDays(brokerageFrozenDays) .setUnfreezeTime(unfreezeTime); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java new file mode 100644 index 000000000..01d0be8c8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.trade.convert.brokerage.user; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * 分销用户 Convert + * + * @author owen + */ +@Mapper +public interface BrokerageUserConvert { + + BrokerageUserConvert INSTANCE = Mappers.getMapper(BrokerageUserConvert.class); + + BrokerageUserRespVO convert(BrokerageUserDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + default PageResult convertPage(PageResult pageResult, + Map userMap, + Map brokerageUserCountMap, + Map userOrderSummaryMap) { + PageResult result = convertPage(pageResult); + for (BrokerageUserRespVO vo : result.getList()) { + // 用户信息 + Optional.ofNullable(userMap.get(vo.getId())) + .ifPresent(user -> { + vo.setNickname(user.getNickname()); + vo.setAvatar(user.getAvatar()); + }); + + // 推广用户数量(一级) + vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); + + Optional orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); + // 推广订单数量 + vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)); + // 推广订单金额 + vo.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); + + // todo 已提现次数 + vo.setWithdrawCount(0); + // todo 已提现金额 + vo.setWithdrawPrice(0); + } + return result; + } + + BrokerageUserDTO convertDTO(BrokerageUserDO brokerageUser); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java deleted file mode 100644 index 1a62bded0..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/TradeBrokerageUserConvert.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.trade.convert.brokerage.user; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 分销用户 Convert - * - * @author owen - */ -@Mapper -public interface TradeBrokerageUserConvert { - - TradeBrokerageUserConvert INSTANCE = Mappers.getMapper(TradeBrokerageUserConvert.class); - - TradeBrokerageUserRespVO convert(TradeBrokerageUserDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index d8ee8950d..e4c996da5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; @@ -279,8 +279,8 @@ public interface TradeOrderConvert { default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) - .setPayPrice(item.getPayPrice()).setCount(item.getCount()) - .setSkuFirstBrokeragePrice(sku.getSubCommissionFirstPrice()) - .setSkuSecondBrokeragePrice(sku.getSubCommissionSecondPrice()); + .setBasePrice(item.getPayPrice() * item.getCount()) + .setFirstFixedPrice(sku.getSubCommissionFirstPrice()) + .setSecondFixedPrice(sku.getSubCommissionSecondPrice()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java index bb3f09c52..be69c6075 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/TradeBrokerageRecordDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java @@ -23,7 +23,7 @@ import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor -public class TradeBrokerageRecordDO extends BaseDO { +public class BrokerageRecordDO extends BaseDO { /** * 编号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java similarity index 75% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java index 3f1cc73aa..1773e41e7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/TradeBrokerageUserDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java @@ -8,7 +8,6 @@ import lombok.*; import java.time.LocalDateTime; -// TODO @疯狂:因为独立了表,是不是可以把字段的 brokerage 去掉了哈? /** * 分销用户 DO * @@ -22,25 +21,26 @@ import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor -public class TradeBrokerageUserDO extends BaseDO { +public class BrokerageUserDO extends BaseDO { /** * 用户编号 + *

+ * 对应 MemberUserDO 的 id 字段 */ @TableId private Long id; - // TODO @疯狂:貌似改成 bindUserId,更明确? /** * 推广员编号 - * + *

* 关联 MemberUserDO 的 id 字段 */ - private Long brokerageUserId; + private Long bindUserId; /** * 推广员绑定时间 */ - private LocalDateTime brokerageBindTime; + private LocalDateTime bindUserTime; /** * 推广资格 @@ -54,10 +54,10 @@ public class TradeBrokerageUserDO extends BaseDO { /** * 可用佣金 */ - private Integer brokeragePrice; + private Integer price; /** * 冻结佣金 */ - private Integer frozenBrokeragePrice; + private Integer frozenPrice; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java new file mode 100644 index 000000000..9f9aae824 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 佣金记录 Mapper + * + * @author owen + */ +@Mapper +public interface BrokerageRecordMapper extends BaseMapperX { + + default PageResult selectPage(BrokerageRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType()) + .eqIfPresent(BrokerageRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(BrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(BrokerageRecordDO::getId)); + } + + default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { + return selectList(new LambdaQueryWrapper() + .eq(BrokerageRecordDO::getStatus, status) + .lt(BrokerageRecordDO::getUnfreezeTime, unfreezeTime)); + } + + default int updateByIdAndStatus(Integer id, Integer status, BrokerageRecordDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(BrokerageRecordDO::getId, id) + .eq(BrokerageRecordDO::getStatus, status)); + } + + default BrokerageRecordDO selectByBizTypeAndBizId(Integer bizType, String bizId) { + return selectOne(BrokerageRecordDO::getBizType, bizType, + BrokerageRecordDO::getBizId, bizId); + } + + @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") + UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, + @Param("bizType") Integer bizType, + @Param("status") Integer status); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java deleted file mode 100644 index 41ed8bad9..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/TradeBrokerageRecordMapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 佣金记录 Mapper - * - * @author owen - */ -@Mapper -public interface TradeBrokerageRecordMapper extends BaseMapperX { - - default PageResult selectPage(TradeBrokerageRecordPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(TradeBrokerageRecordDO::getUserId, reqVO.getUserId()) - .eqIfPresent(TradeBrokerageRecordDO::getBizType, reqVO.getBizType()) - .eqIfPresent(TradeBrokerageRecordDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(TradeBrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TradeBrokerageRecordDO::getId)); - } - - default List selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { - return selectList(new LambdaQueryWrapper() - .eq(TradeBrokerageRecordDO::getStatus, status) - .lt(TradeBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); - } - - default int updateByIdAndStatus(Integer id, Integer status, TradeBrokerageRecordDO updateObj) { - return update(updateObj, new LambdaQueryWrapper() - .eq(TradeBrokerageRecordDO::getId, id) - .eq(TradeBrokerageRecordDO::getStatus, status)); - } - - // TODO @疯狂:userId??? - default TradeBrokerageRecordDO selectByUserIdAndBizTypeAndBizId(Integer bizType, String bizId) { - return selectOne(TradeBrokerageRecordDO::getBizType, bizType, - TradeBrokerageRecordDO::getBizId, bizId); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java new file mode 100644 index 000000000..ee90b3e7d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 分销用户 Mapper + * + * @author owen + */ +@Mapper +public interface BrokerageUserMapper extends BaseMapperX { + + default PageResult selectPage(BrokerageUserPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(BrokerageUserDO::getBindUserId, reqVO.getBindUserId()) + .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) + .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(BrokerageUserDO::getId)); + } + + /** + * 更新用户可用佣金(增加) + * + * @param id 用户编号 + * @param incrCount 增加佣金(正数) + */ + default void updatePriceIncr(Long id, Integer incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" price = price + " + incrCount) + .eq(BrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户可用佣金(减少) + * 注意:理论上佣金可能已经提现,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 增加佣金(负数) + */ + default void updatePriceDecr(Long id, Integer incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" price = price + " + incrCount) // 负数,所以使用 + 号 + .eq(BrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(增加) + * + * @param id 用户编号 + * @param incrCount 增加冻结佣金(正数) + */ + default void updateFrozenPriceIncr(Long id, Integer incrCount) { + Assert.isTrue(incrCount > 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_price = frozen_price + " + incrCount) + .eq(BrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(减少) + * 注意:理论上冻结佣金可能已经解冻,这时会扣出负数,确保平台不会造成损失 + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + */ + default void updateFrozenPriceDecr(Long id, Integer incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_price = frozen_price + " + incrCount) // 负数,所以使用 + 号 + .eq(BrokerageUserDO::getId, id); + update(null, lambdaUpdateWrapper); + } + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + * @return 更新条数 + */ + default int updateFrozenPriceDecrAndPriceIncr(Long id, Integer incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_price = frozen_price + " + incrCount + // 负数,所以使用 + 号 + ", price = price + " + -incrCount) // 负数,所以使用 - 号 + .eq(BrokerageUserDO::getId, id) + .ge(BrokerageUserDO::getFrozenPrice, -incrCount); // cas 逻辑 + return update(null, lambdaUpdateWrapper); + } + + default void updateBindUserIdAndBindUserTimeToNull(Long id) { + update(null, new LambdaUpdateWrapper() + .eq(BrokerageUserDO::getId, id) + .set(BrokerageUserDO::getBindUserId, null).set(BrokerageUserDO::getBindUserTime, null)); + } + + default void updateEnabledFalseAndBrokerageTimeToNull(Long id) { + update(null, new LambdaUpdateWrapper() + .eq(BrokerageUserDO::getId, id) + .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java deleted file mode 100644 index f0c221311..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/TradeBrokerageUserMapper.java +++ /dev/null @@ -1,103 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user; - -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; - -/** - * 分销用户 Mapper - * - * @author owen - */ -@Mapper -public interface TradeBrokerageUserMapper extends BaseMapperX { - - default PageResult selectPage(TradeBrokerageUserPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(TradeBrokerageUserDO::getBrokerageUserId, reqVO.getBrokerageUserId()) - .eqIfPresent(TradeBrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) - .betweenIfPresent(TradeBrokerageUserDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TradeBrokerageUserDO::getId)); - } - - /** - * 更新用户可用佣金(增加) - * - * @param id 用户编号 - * @param incrCount 增加佣金(正数) - */ - default void updateBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount > 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) - .eq(TradeBrokerageUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户可用佣金(减少) - * 注意:理论上佣金可能已经提现,这时会扣出负数,确保平台不会造成损失 - * - * @param id 用户编号 - * @param incrCount 增加佣金(负数) - */ - default void updateBrokeragePriceDecr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" brokerage_price = brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(TradeBrokerageUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(增加) - * - * @param id 用户编号 - * @param incrCount 增加冻结佣金(正数) - */ - default void updateFrozenBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount > 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) - .eq(TradeBrokerageUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(减少) - * 注意:理论上冻结佣金可能已经解冻,这时会扣出负数,确保平台不会造成损失 - * - * @param id 用户编号 - * @param incrCount 减少冻结佣金(负数) - */ - default void updateFrozenBrokeragePriceDecr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount) // 负数,所以使用 + 号 - .eq(TradeBrokerageUserDO::getId, id); - update(null, lambdaUpdateWrapper); - } - - /** - * 更新用户冻结佣金(减少), 更新用户佣金(增加) - * - * @param id 用户编号 - * @param incrCount 减少冻结佣金(负数) - * @return 更新条数 - */ - default int updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int incrCount) { - Assert.isTrue(incrCount < 0); - LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() - .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 - ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 - .eq(TradeBrokerageUserDO::getId, id) - .ge(TradeBrokerageUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 - return update(null, lambdaUpdateWrapper); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java similarity index 63% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java index 94218d47e..c221408e5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/TradeBrokerageRecordUnfreezeJob.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/job/brokerage/BrokerageRecordUnfreezeJob.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.job.brokerage; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; import org.springframework.stereotype.Component; import javax.annotation.Resource; @@ -15,14 +15,14 @@ import javax.annotation.Resource; */ @Component @TenantJob -public class TradeBrokerageRecordUnfreezeJob implements JobHandler { +public class BrokerageRecordUnfreezeJob implements JobHandler { @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @Override public String execute(String param) { - int count = tradeBrokerageRecordService.unfreezeRecord(); + int count = brokerageRecordService.unfreezeRecord(); return StrUtil.format("解冻佣金 {} 个", count); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java new file mode 100644 index 000000000..07e07817e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +/** + * 佣金 增加 Request BO + * + * @author owen + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BrokerageAddReqBO { + + /** + * 业务编号 + */ + @NotBlank(message = "业务编号不能为空") + private String bizId; + /** + * 佣金基数 + */ + private Integer basePrice; + /** + * 一级佣金(固定) + */ + private Integer firstFixedPrice; + /** + * 二级佣金(固定) + */ + private Integer secondFixedPrice; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java new file mode 100644 index 000000000..ffbb3ed9a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/UserBrokerageSummaryBO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 用户佣金合计 BO + * + * @author owen + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserBrokerageSummaryBO { + /** + * 佣金数量 + */ + private Integer count; + /** + * 佣金总额 + */ + private Integer price; +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java new file mode 100644 index 000000000..64e5fe52f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.record; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 佣金记录 Service 接口 + * + * @author owen + */ +public interface BrokerageRecordService { + + /** + * 获得佣金记录 + * + * @param id 编号 + * @return 佣金记录 + */ + BrokerageRecordDO getBrokerageRecord(Integer id); + + /** + * 获得佣金记录分页 + * + * @param pageReqVO 分页查询 + * @return 佣金记录分页 + */ + PageResult getBrokerageRecordPage(BrokerageRecordPageReqVO pageReqVO); + + /** + * 增加佣金 + * + * @param userId 会员编号 + * @param bizType 业务类型 + * @param list 请求参数列表 + */ + void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, @Valid List list); + + /** + * 取消佣金:将佣金记录,状态修改为已失效 + * + * @param userId 会员编号 + * @param bizType 业务类型 + * @param bizId 业务编号 + */ + void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId); + + /** + * 解冻佣金:将待结算的佣金记录,状态修改为已结算 + * + * @return 解冻佣金的数量 + */ + int unfreezeRecord(); + + /** + * 汇总用户佣金 + * + * @param userId 用户编号 + * @param bizType 业务类型 + * @param status 佣金状态 + * @return 用户佣金汇总 + */ + UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java new file mode 100644 index 000000000..960b45ae5 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java @@ -0,0 +1,235 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.record; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * 佣金记录 Service 实现类 + * + * @author owen + */ +@Slf4j +@Service +@Validated +public class BrokerageRecordServiceImpl implements BrokerageRecordService { + + @Resource + private BrokerageRecordMapper brokerageRecordMapper; + @Resource + private TradeConfigService tradeConfigService; + @Resource + private BrokerageUserService brokerageUserService; + + @Override + public BrokerageRecordDO getBrokerageRecord(Integer id) { + return brokerageRecordMapper.selectById(id); + } + + @Override + public PageResult getBrokerageRecordPage(BrokerageRecordPageReqVO pageReqVO) { + return brokerageRecordMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, List list) { + TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); + // 0 未启用分销功能 + if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { + log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,userId({})", userId); + return; + } + + // 1.1 获得一级推广人 + BrokerageUserDO firstUser = brokerageUserService.getBindBrokerageUser(userId); + if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { + return; + } + // 1.2 计算一级分佣 + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstFixedPrice, bizType); + + // 2.1 获得二级推广员 + if (firstUser.getBindUserId() == null) { + return; + } + BrokerageUserDO secondUser = brokerageUserService.getBrokerageUser(firstUser.getBindUserId()); + if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { + return; + } + // 2.2 计算二级分佣 + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSecondFixedPrice, bizType); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { + BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId); + if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { + log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); + return; + } + + // 1. 更新佣金记录为已失效 + BrokerageRecordDO updateObj = new BrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); + int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + if (updateRows == 0) { + log.error("[cancelBrokerage][record({}) 更新为已失效失败]", record.getId()); + return; + } + + // 2. 更新用户的佣金 + if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { + brokerageUserService.updateUserFrozenPrice(userId, -record.getPrice()); + } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { + brokerageUserService.updateUserPrice(userId, -record.getPrice()); + } + } + + /** + * 计算佣金 + * + * @param basePrice 佣金基数 + * @param percent 佣金比例 + * @param fixedPrice 固定佣金 + * @return 佣金 + */ + int calculatePrice(Integer basePrice, Integer percent, Integer fixedPrice) { + // 1. 优先使用固定佣金 + if (fixedPrice != null && fixedPrice > 0) { + return ObjectUtil.defaultIfNull(fixedPrice, 0); + } + // 2. 根据比例计算佣金 + if (basePrice != null && basePrice > 0 && percent != null && percent > 0) { + return MoneyUtils.calculateRatePriceFloor(basePrice, Double.valueOf(percent)); + } + return 0; + } + + /** + * 增加用户佣金 + * + * @param user 用户 + * @param list 佣金增加参数列表 + * @param brokerageFrozenDays 冻结天数 + * @param brokeragePercent 佣金比例 + * @param fixedPriceFun 固定佣金 + * @param bizType 业务类型 + */ + private void addBrokerage(BrokerageUserDO user, List list, Integer brokerageFrozenDays, + Integer brokeragePercent, Function fixedPriceFun, + BrokerageRecordBizTypeEnum bizType) { + // 1.1 处理冻结时间 + LocalDateTime unfreezeTime = null; + if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { + unfreezeTime = LocalDateTime.now().plusDays(brokerageFrozenDays); + } + // 1.2 计算分佣 + int totalBrokerage = 0; + List records = new ArrayList<>(); + for (BrokerageAddReqBO item : list) { + int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPriceFun.apply(item)); + if (brokeragePerItem <= 0) { + continue; + } + records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), + brokerageFrozenDays, brokeragePerItem, unfreezeTime, bizType.getTitle())); + totalBrokerage += brokeragePerItem; + } + if (CollUtil.isEmpty(records)) { + return; + } + // 1.3 保存佣金记录 + brokerageRecordMapper.insertBatch(records); + + // 2. 更新用户佣金 + if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { // 更新用户冻结佣金 + brokerageUserService.updateUserFrozenPrice(user.getId(), totalBrokerage); + } else { // 更新用户可用佣金 + brokerageUserService.updateUserPrice(user.getId(), totalBrokerage); + } + } + + @Override + public int unfreezeRecord() { + // 1. 查询待结算的佣金记录 + List records = brokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( + BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); + if (CollUtil.isEmpty(records)) { + return 0; + } + + // 2. 遍历执行 + int count = 0; + for (BrokerageRecordDO record : records) { + try { + boolean success = getSelf().unfreezeRecord(record); + if (success) { + count++; + } + } catch (Exception e) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId(), e); + } + } + return count; + } + + @Override + public UserBrokerageSummaryBO summaryByUserIdAndBizTypeAndStatus(Long userId, Integer bizType, Integer status) { + UserBrokerageSummaryBO summaryBO = brokerageRecordMapper.selectCountAndSumPriceByUserIdAndBizTypeAndStatus(userId, bizType, status); + return summaryBO == null ? new UserBrokerageSummaryBO(0, 0) : summaryBO; + } + + @Transactional(rollbackFor = Exception.class) + public boolean unfreezeRecord(BrokerageRecordDO record) { + // 更新记录状态 + BrokerageRecordDO updateObj = new BrokerageRecordDO() + .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) + .setUnfreezeTime(LocalDateTime.now()); + int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + if (updateRows == 0) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); + return false; + } + + // 更新用户冻结佣金 + brokerageUserService.updateFrozenPriceDecrAndPriceIncr(record.getUserId(), -record.getPrice()); + log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); + return true; + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private BrokerageRecordServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java deleted file mode 100644 index 91c61882f..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordService.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.record; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; - -import java.util.List; - -/** - * 佣金记录 Service 接口 - * - * @author owen - */ -public interface TradeBrokerageRecordService { - - /** - * 获得佣金记录 - * - * @param id 编号 - * @return 佣金记录 - */ - TradeBrokerageRecordDO getBrokerageRecord(Integer id); - - /** - * 获得佣金记录分页 - * - * @param pageReqVO 分页查询 - * @return 佣金记录分页 - */ - PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO); - - // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; - /** - * 增加佣金 - * - * @param userId 会员编号 - * @param list 请求参数列表 - */ - void addBrokerage(Long userId, List list); - - // TODO @疯狂:是不是 bizType 得加下?方便未来拓展哈; - /** - * 取消佣金:将佣金记录,状态修改为已失效 - * - * @param userId 会员编号 - * @param bizId 业务编号 - */ - void cancelBrokerage(Long userId, String bizId); - - /** - * 解冻佣金:将待结算的佣金记录,状态修改为已结算 - * - * @return 解冻佣金的数量 - */ - int unfreezeRecord(); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java deleted file mode 100644 index 8ced49abb..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImpl.java +++ /dev/null @@ -1,233 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.record; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.BooleanUtil; -import cn.hutool.core.util.NumberUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.convert.brokerage.record.TradeBrokerageRecordConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; -import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.math.RoundingMode; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -/** - * 佣金记录 Service 实现类 - * - * @author owen - */ -@Slf4j -@Service -@Validated -public class TradeBrokerageRecordServiceImpl implements TradeBrokerageRecordService { - - @Resource - private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; - @Resource - private TradeConfigService tradeConfigService; - @Resource - private TradeBrokerageUserService tradeBrokerageUserService; - - @Override - public TradeBrokerageRecordDO getBrokerageRecord(Integer id) { - return tradeBrokerageRecordMapper.selectById(id); - } - - @Override - public PageResult getBrokerageRecordPage(TradeBrokerageRecordPageReqVO pageReqVO) { - return tradeBrokerageRecordMapper.selectPage(pageReqVO); - } - - // TODO @疯狂:buyerId 要不要统一改成 userId 哈; - @Override - @Transactional(rollbackFor = Exception.class) - public void addBrokerage(Long buyerId, List list) { - TradeConfigDO memberConfig = tradeConfigService.getTradeConfig(); - // 0 未启用分销功能 - // TODO @疯狂:BooleanUtil.isFalse();逻辑里,尽量不做 !取反,这样要多思考一层; - if (memberConfig == null || !BooleanUtil.isTrue(memberConfig.getBrokerageEnabled())) { - log.warn("[addBrokerage][增加佣金失败:brokerageEnabled 未配置,buyerId({})", buyerId); - return; - } - - // 1.1 获得一级推广人 - TradeBrokerageUserDO firstUser = tradeBrokerageUserService.getInviteBrokerageUser(buyerId); - if (firstUser == null || !BooleanUtil.isTrue(firstUser.getBrokerageEnabled())) { - return; - } - - // 1.2 计算一级分佣 // TODO 疯狂:类似 1.1 和 1.2 的空行,可以去掉;一般在代码里的空行,是为了逻辑分块;但是分块如果太多,就会导致代码里都是空行哈; - addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getSkuFirstBrokeragePrice); - - // 2.1 获得二级推广员 - // TODO @疯狂:这里可以加个 firstUser.getBrokerageUserId() 为空的判断 return - TradeBrokerageUserDO secondUser = tradeBrokerageUserService.getBrokerageUser(firstUser.getBrokerageUserId()); - if (secondUser == null || !BooleanUtil.isTrue(secondUser.getBrokerageEnabled())) { - return; - } - - // 2.2 计算二级分佣 - addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSkuSecondBrokeragePrice); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void cancelBrokerage(Long userId, String bizId) { - TradeBrokerageRecordDO record = tradeBrokerageRecordMapper.selectByUserIdAndBizTypeAndBizId(BrokerageRecordBizTypeEnum.ORDER.getType(), bizId); - if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { - log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); - return; - } - - // 1. 更新佣金记录为已失效 - TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO().setStatus(BrokerageRecordStatusEnum.CANCEL.getStatus()); - int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); - if (updateRows == 0) { - log.error("[cancelBrokerage][record({}) 更新为已失效失败]", record.getId()); - return; - } - - // 2. 更新用户的佣金 - if (BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus().equals(record.getStatus())) { - tradeBrokerageUserService.updateUserFrozenBrokeragePrice(userId, -record.getPrice()); - } else if (BrokerageRecordStatusEnum.SETTLEMENT.getStatus().equals(record.getStatus())) { - tradeBrokerageUserService.updateUserBrokeragePrice(userId, -record.getPrice()); - } - } - - // TODO @疯狂:是不是 calculateBrokeragePrice - /** - * 计算佣金 - * - * @param payPrice 订单支付金额 - * @param percent 商品 SKU 设置的佣金 - * @param skuBrokeragePrice 商品的佣金 - * @return 佣金 - */ - int calculateBrokerage(Integer payPrice, Integer percent, Integer skuBrokeragePrice) { - // 1. 优先使用商品 SKU 设置的佣金 - if (skuBrokeragePrice != null && skuBrokeragePrice > 0) { - return ObjectUtil.defaultIfNull(skuBrokeragePrice, 0); - } - // 2. 根据订单支付金额计算佣金 - // TODO @疯狂:要不要把 MoneyUtils 抽到 common 里,然后这里也使用这个类的方法; - if (payPrice != null && payPrice > 0 && percent != null && percent > 0) { - return NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue(); - } - return 0; - } - - /** - * 增加用户佣金 - * - * @param user 用户 - * @param list 佣金增加参数列表 - * @param brokerageFrozenDays 冻结天数 - * @param brokeragePercent 佣金比例 - * @param skuBrokeragePriceFun 商品 SKU 设置的佣金 - */ - private void addBrokerage(TradeBrokerageUserDO user, List list, Integer brokerageFrozenDays, - Integer brokeragePercent, Function skuBrokeragePriceFun) { - // 1.1 处理冻结时间 - // TODO @疯狂:是不是 brokerageFrozenDays != null && brokerageFrozenDays > 0 ?然后计算;更简洁一点; - brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); - LocalDateTime unfreezeTime = null; - if (brokerageFrozenDays > 0) { - unfreezeTime = LocalDateTime.now().plusDays(brokerageFrozenDays); - } - // 1.2 计算分佣 - int totalBrokerage = 0; - List records = new ArrayList<>(); - for (BrokerageAddReqBO item : list) { - int brokeragePerItem = calculateBrokerage(item.getPayPrice(), brokeragePercent, skuBrokeragePriceFun.apply(item)); - // TODO @疯狂:其实可以 brokeragePerItem <= 0 ,continue;这样 { 层级更少;代码更简洁;} - if (brokeragePerItem > 0) { - int brokerage = brokeragePerItem * item.getCount(); - records.add(TradeBrokerageRecordConvert.INSTANCE.convert(user, item.getBizId(), brokerageFrozenDays, brokerage, unfreezeTime)); - totalBrokerage += brokerage; - } - } - if (CollUtil.isEmpty(records)) { - return; - } - // 1.3 保存佣金记录 - tradeBrokerageRecordMapper.insertBatch(records); - - // 2. 更新用户佣金 - if (brokerageFrozenDays > 0) { // 更新用户冻结佣金 - tradeBrokerageUserService.updateUserFrozenBrokeragePrice(user.getId(), totalBrokerage); - } else { // 更新用户可用佣金 - tradeBrokerageUserService.updateUserBrokeragePrice(user.getId(), totalBrokerage); - } - } - - @Override - public int unfreezeRecord() { - // 1. 查询待结算的佣金记录 - List records = tradeBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( - BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); - if (CollUtil.isEmpty(records)) { - return 0; - } - - // 2. 遍历执行 - int count = 0; - for (TradeBrokerageRecordDO record : records) { - try { - boolean success = getSelf().unfreezeRecord(record); - if (success) { - count++; - } - } catch (Exception e) { - log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId(), e); - } - } - return count; - } - - @Transactional(rollbackFor = Exception.class) - public boolean unfreezeRecord(TradeBrokerageRecordDO record) { - // 更新记录状态 - TradeBrokerageRecordDO updateObj = new TradeBrokerageRecordDO() - .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) - .setUnfreezeTime(LocalDateTime.now()); - int updateRows = tradeBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); - if (updateRows == 0) { - log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); - return false; - } - - // 更新用户冻结佣金 - tradeBrokerageUserService.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(record.getUserId(), -record.getPrice()); - log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); - return true; - } - - /** - * 获得自身的代理对象,解决 AOP 生效问题 - * - * @return 自己 - */ - private TradeBrokerageRecordServiceImpl getSelf() { - return SpringUtil.getBean(getClass()); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java deleted file mode 100644 index d325118a9..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/bo/BrokerageAddReqBO.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.record.bo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -// TODO @疯狂:要不要 service 还是拍平;就是都放在 brokerage 包下,然后 bo 里面,稍微分分; -/** - * 佣金 增加 Request BO - * - * @author owen - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class BrokerageAddReqBO { - - // TODO @疯狂:bo 的话,也可以考虑加下 @Validated 注解,校验下参数;防御性下哈,虽然不一定用的到 - - /** - * 业务ID - */ - private String bizId; - // TODO @疯狂:不需要 payPrice 和 count,计算成 price 就好啦; - /** - * 商品支付价格 - */ - private Integer payPrice; - // TODO @疯狂:可以去掉 sku 哈,更抽象一点; - /** - * SKU 一级佣金 - */ - private Integer skuFirstBrokeragePrice; - /** - * SKU 二级佣金 - */ - private Integer skuSecondBrokeragePrice; - /** - * 购买数量 - */ - private Integer count; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java new file mode 100644 index 000000000..f06bb7ffc --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.user; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; + +import java.util.Collection; +import java.util.List; + +/** + * 分销用户 Service 接口 + * + * @author owen + */ +public interface BrokerageUserService { + + /** + * 获得分销用户 + * + * @param id 编号 + * @return 分销用户 + */ + BrokerageUserDO getBrokerageUser(Long id); + + /** + * 获得分销用户列表 + * + * @param ids 编号 + * @return 分销用户列表 + */ + List getBrokerageUserList(Collection ids); + + /** + * 获得分销用户分页 + * + * @param pageReqVO 分页查询 + * @return 分销用户分页 + */ + PageResult getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO); + + /** + * 修改推广员编号 + * + * @param id 用户编号 + * @param bindUserId 推广员编号 + */ + void updateBrokerageUserId(Long id, Long bindUserId); + + /** + * 修改推广资格 + * + * @param id 用户编号 + * @param enabled 推广资格 + */ + void updateBrokerageEnabled(Long id, Boolean enabled); + + /** + * 获得用户的推广人 + * + * @param id 用户编号 + * @return 用户的推广人 + */ + BrokerageUserDO getBindBrokerageUser(Long id); + + /** + * 更新用户佣金 + * + * @param id 用户编号 + * @param price 用户可用佣金 + */ + void updateUserPrice(Long id, Integer price); + + /** + * 更新用户冻结佣金 + * + * @param id 用户编号 + * @param frozenPrice 用户冻结佣金 + */ + void updateUserFrozenPrice(Long id, Integer frozenPrice); + + /** + * 更新用户冻结佣金(减少), 更新用户佣金(增加) + * + * @param id 用户编号 + * @param frozenPrice 减少冻结佣金(负数) + */ + void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice); + + /** + * 获得推广用户数量(一级) + * + * @param bindUserId 绑定的推广员编号 + * @return 推广用户数量 + */ + Long getCountByBindUserId(Long bindUserId); + + /** + * 【会员】绑定推广员 + * + * @param userId 用户编号 + * @param bindUserId 推广员编号 + * @param isNewUser 是否为新用户 + * @return 是否绑定 + */ + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java new file mode 100644 index 000000000..6d6d7d2ac --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java @@ -0,0 +1,210 @@ +package cn.iocoder.yudao.module.trade.service.brokerage.user; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.BooleanUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; + +/** + * 分销用户 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class BrokerageUserServiceImpl implements BrokerageUserService { + + @Resource + private BrokerageUserMapper brokerageUserMapper; + + @Resource + private TradeConfigService tradeConfigService; + + @Override + public BrokerageUserDO getBrokerageUser(Long id) { + return brokerageUserMapper.selectById(id); + } + + @Override + public List getBrokerageUserList(Collection ids) { + return brokerageUserMapper.selectBatchIds(ids); + } + + @Override + public PageResult getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) { + return brokerageUserMapper.selectPage(pageReqVO); + } + + @Override + public void updateBrokerageUserId(Long id, Long bindUserId) { + // 校验存在 + validateBrokerageUserExists(id); + if (bindUserId == null) { + // 清除推广员 + brokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id); + } else { + // 修改推广员 + brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); + } + } + + @Override + public void updateBrokerageEnabled(Long id, Boolean enabled) { + // 校验存在 + validateBrokerageUserExists(id); + if (BooleanUtil.isTrue(enabled)) { + // 开通推广资格 + brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) + .setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now())); + } else { + // 取消推广资格 + brokerageUserMapper.updateEnabledFalseAndBrokerageTimeToNull(id); + } + } + + private void validateBrokerageUserExists(Long id) { + if (brokerageUserMapper.selectById(id) == null) { + throw exception(BROKERAGE_USER_NOT_EXISTS); + } + } + + @Override + public BrokerageUserDO getBindBrokerageUser(Long id) { + return Optional.ofNullable(id) + .map(this::getBrokerageUser) + .map(BrokerageUserDO::getBindUserId) + .map(this::getBrokerageUser) + .orElse(null); + } + + @Override + public void updateUserPrice(Long id, Integer price) { + if (price > 0) { + brokerageUserMapper.updatePriceIncr(id, price); + } else if (price < 0) { + brokerageUserMapper.updatePriceDecr(id, price); + } + } + + @Override + public void updateUserFrozenPrice(Long id, Integer frozenPrice) { + if (frozenPrice > 0) { + brokerageUserMapper.updateFrozenPriceIncr(id, frozenPrice); + } else if (frozenPrice < 0) { + brokerageUserMapper.updateFrozenPriceDecr(id, frozenPrice); + } + } + + @Override + public void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice) { + Assert.isTrue(frozenPrice < 0); + int updateRows = brokerageUserMapper.updateFrozenPriceDecrAndPriceIncr(id, frozenPrice); + if (updateRows == 0) { + throw exception(BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH); + } + } + + @Override + public Long getCountByBindUserId(Long bindUserId) { + return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); + } + + @Override + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) { + if (userId == null) { + throw exception(0); + } + + boolean isInsert = false; + BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); + // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开 + if (brokerageUser == null) { + isInsert = true; + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0); + } + + // 校验能否绑定 + boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser); + if (!validated) { + return false; + } + + if (isInsert) { + Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition(); + if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { + // 人人分销:用户默认就有分销资格 + brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now()); + } + brokerageUserMapper.insert(brokerageUser); + } else { + brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId) + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); + } + return true; + } + + private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) { + if (bindUserId == null) { + return false; + } + + // 校验分销功能是否启用 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { + return false; + } + + // 校验绑定自己 + if (Objects.equals(user.getId(), bindUserId)) { + throw exception(BROKERAGE_BIND_SELF); + } + + // 校验要绑定的用户有无推广资格 + BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId); + if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) { + throw exception(BROKERAGE_BIND_USER_NOT_ENABLED); + } + + // 校验分佣模式:仅可后台手动设置推广员 + if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) { + throw exception(BROKERAGE_BIND_CONDITION_ADMIN); + } + + // 校验分销关系绑定模式 + if (BrokerageBindModeEnum.REGISTER.getMode().equals(tradeConfig.getBrokerageBindMode())) { + if (!BooleanUtil.isTrue(isNewUser)) { + throw exception(BROKERAGE_BIND_MODE_REGISTER); // 只有在注册时可以绑定 + } + } else if (BrokerageBindModeEnum.ANYTIME.getMode().equals(tradeConfig.getBrokerageBindMode())) { + if (user.getBindUserId() != null) { + throw exception(BROKERAGE_BIND_OVERRIDE); // 已绑定了推广人 + } + } + + // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!! + if (Objects.equals(user.getId(), bindUser.getBindUserId())) { + throw exception(BROKERAGE_BIND_LOOP); + } + return true; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java deleted file mode 100644 index 54913b98a..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserService.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.user; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; - -import java.util.Collection; -import java.util.List; - -// TODO @疯狂:要不去掉 Trade 前缀哈;交易这块,我准备除了 tradeorder 保持下,类似 aftersale,都要取消前缀了;tradeorder 保持的原因,是避免 payorder 和它重复 -/** - * 分销用户 Service 接口 - * - * @author owen - */ -public interface TradeBrokerageUserService { - - /** - * 获得分销用户 - * - * @param id 编号 - * @return 分销用户 - */ - TradeBrokerageUserDO getBrokerageUser(Long id); - - /** - * 获得分销用户列表 - * - * @param ids 编号 - * @return 分销用户列表 - */ - List getBrokerageUserList(Collection ids); - - /** - * 获得分销用户分页 - * - * @param pageReqVO 分页查询 - * @return 分销用户分页 - */ - PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO); - - /** - * 修改推广员编号 - * - * @param id 用户编号 - * @param brokerageUserId 推广员编号 - */ - void updateBrokerageUserId(Long id, Long brokerageUserId); - - /** - * 修改推广资格 - * - * @param id 用户编号 - * @param brokerageEnabled 推广资格 - */ - void updateBrokerageEnabled(Long id, Boolean brokerageEnabled); - - /** - * 获得用户的推广人 - * - * @param id 用户编号 - * @return 用户的推广人 - */ - TradeBrokerageUserDO getInviteBrokerageUser(Long id); - - /** - * 更新用户佣金 - * - * @param id 用户编号 - * @param brokeragePrice 用户可用佣金 - */ - void updateUserBrokeragePrice(Long id, int brokeragePrice); - - // TODO @疯狂:int 类型一般不用哈;尽量都用封装类型;不差这点内存哈; - /** - * 更新用户冻结佣金 - * - * @param id 用户编号 - * @param frozenBrokeragePrice 用户冻结佣金 - */ - void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice); - - /** - * 更新用户冻结佣金(减少), 更新用户佣金(增加) - * - * @param id 用户编号 - * @param frozenBrokeragePrice 减少冻结佣金(负数) - */ - void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java deleted file mode 100644 index c4300c1ae..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.brokerage.user; - -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS; - -/** - * 分销用户 Service 实现类 - * - * @author owen - */ -@Service -@Validated -public class TradeBrokerageUserServiceImpl implements TradeBrokerageUserService { - - @Resource - private TradeBrokerageUserMapper brokerageUserMapper; - - @Override - public TradeBrokerageUserDO getBrokerageUser(Long id) { - return brokerageUserMapper.selectById(id); - } - - @Override - public List getBrokerageUserList(Collection ids) { - return brokerageUserMapper.selectBatchIds(ids); - } - - @Override - public PageResult getBrokerageUserPage(TradeBrokerageUserPageReqVO pageReqVO) { - return brokerageUserMapper.selectPage(pageReqVO); - } - - @Override - public void updateBrokerageUserId(Long id, Long brokerageUserId) { - // 校验存在 - validateBrokerageUserExists(id); - // TODO @疯狂:貌似没实现完 - } - - @Override - public void updateBrokerageEnabled(Long id, Boolean brokerageEnabled) { - // 校验存在 - validateBrokerageUserExists(id); - // TODO @疯狂:貌似没实现完 - } - - private void validateBrokerageUserExists(Long id) { - if (brokerageUserMapper.selectById(id) == null) { - throw exception(BROKERAGE_USER_NOT_EXISTS); - } - } - - // TODO @疯狂:getBindBrokerageUser 会不会好点,因为统一使用 Bind 替代了 Invite - @Override - public TradeBrokerageUserDO getInviteBrokerageUser(Long id) { - return Optional.ofNullable(id) - .map(this::getBrokerageUser) - .map(TradeBrokerageUserDO::getBrokerageUserId) - .map(this::getBrokerageUser) - .orElse(null); - } - - // TODO @疯狂:单个更新,不用事务哈; - @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserBrokeragePrice(Long id, int brokeragePrice) { - if (brokeragePrice > 0) { - brokerageUserMapper.updateBrokeragePriceIncr(id, brokeragePrice); - } else if (brokeragePrice < 0) { - brokerageUserMapper.updateBrokeragePriceDecr(id, brokeragePrice); - } - } - - // TODO @疯狂:单个更新,不用事务哈; - @Override - @Transactional(rollbackFor = Exception.class) - public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { - if (frozenBrokeragePrice > 0) { - brokerageUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); - } else if (frozenBrokeragePrice < 0) { - brokerageUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); - } - } - - // TODO @疯狂:单个更新,不用事务哈; - @Override - @Transactional(rollbackFor = Exception.class) - public void updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(Long id, int frozenBrokeragePrice) { - Assert.isTrue(frozenBrokeragePrice < 0); - int updateRows = brokerageUserMapper.updateFrozenBrokeragePriceDecrAndBrokeragePriceIncr(id, frozenBrokeragePrice); - if (updateRows == 0) { - // TODO @疯狂:挪到 trade 这变的错误码哈; - throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); - } - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 94fdfe17e..85d4caae0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -11,8 +11,6 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.trade.service.brokerage.record.TradeBrokerageRecordService; -import cn.iocoder.yudao.module.trade.service.brokerage.record.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.point.MemberPointApi; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -51,9 +49,12 @@ import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.dal.redis.no.TradeOrderNoRedisDAO; import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; @@ -128,7 +129,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private MemberPointApi memberPointApi; @Resource - private TradeBrokerageRecordService tradeBrokerageRecordService; + private BrokerageRecordService brokerageRecordService; @Resource private ProductCommentApi productCommentApi; @@ -394,7 +395,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 增加用户经验 getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); // 增加用户佣金 - getSelf().addBrokerageAsync(order.getUserId(), order.getId()); + getSelf().addBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, order.getId()); } /** @@ -674,7 +675,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 扣减用户经验 getSelf().reduceUserExperienceAsync(order.getUserId(), orderRefundPrice, afterSaleId); // 更新分佣记录为已失效 - getSelf().cancelBrokerageAsync(order.getUserId(), id); + getSelf().cancelBrokerageAsync(order.getUserId(), BrokerageRecordBizTypeEnum.ORDER, id); } @Override @@ -784,16 +785,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Async - protected void addBrokerageAsync(Long userId, Long orderId) { + protected void addBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderId) { List orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); List list = convertList(orderItems, item -> TradeOrderConvert.INSTANCE.convert(item, productSkuApi.getSku(item.getSkuId()))); - tradeBrokerageRecordService.addBrokerage(userId, list); + brokerageRecordService.addBrokerage(userId, bizType, list); } @Async - protected void cancelBrokerageAsync(Long userId, Long orderItemId) { - tradeBrokerageRecordService.cancelBrokerage(userId, String.valueOf(orderItemId)); + protected void cancelBrokerageAsync(Long userId, BrokerageRecordBizTypeEnum bizType, Long orderItemId) { + brokerageRecordService.cancelBrokerage(userId, bizType, String.valueOf(orderItemId)); } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java similarity index 58% rename from yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java index 9daf3cafb..abf2b37c1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/TradeBrokerageRecordServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImplTest.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record; import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.TradeBrokerageRecordPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.TradeBrokerageRecordDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.TradeBrokerageRecordMapper; -import cn.iocoder.yudao.module.trade.service.brokerage.user.TradeBrokerageUserService; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper; +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -27,51 +27,51 @@ import static org.junit.jupiter.api.Assertions.assertEquals; // TODO @芋艿:单测后续看看 /** - * {@link TradeBrokerageRecordServiceImpl} 的单元测试类 + * {@link BrokerageRecordServiceImpl} 的单元测试类 * * @author owen */ -@Import(TradeBrokerageRecordServiceImpl.class) -public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { +@Import(BrokerageRecordServiceImpl.class) +public class BrokerageRecordServiceImplTest extends BaseDbUnitTest { @Resource - private TradeBrokerageRecordServiceImpl tradeBrokerageRecordService; + private BrokerageRecordServiceImpl brokerageRecordService; @Resource - private TradeBrokerageRecordMapper tradeBrokerageRecordMapper; + private BrokerageRecordMapper brokerageRecordMapper; @MockBean private TradeConfigService tradeConfigService; @MockBean - private TradeBrokerageUserService tradeBrokerageUserService; + private BrokerageUserService brokerageUserService; @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetBrokerageRecordPage() { // mock 数据 - TradeBrokerageRecordDO dbBrokerageRecord = randomPojo(TradeBrokerageRecordDO.class, o -> { // 等会查询到 + BrokerageRecordDO dbBrokerageRecord = randomPojo(BrokerageRecordDO.class, o -> { // 等会查询到 o.setUserId(null); o.setBizType(null); o.setStatus(null); o.setCreateTime(null); }); - tradeBrokerageRecordMapper.insert(dbBrokerageRecord); + brokerageRecordMapper.insert(dbBrokerageRecord); // 测试 userId 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setUserId(null))); // 测试 bizType 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setBizType(null))); // 测试 status 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setStatus(null))); // 测试 createTime 不匹配 - tradeBrokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null))); + brokerageRecordMapper.insert(cloneIgnoreId(dbBrokerageRecord, o -> o.setCreateTime(null))); // 准备参数 - TradeBrokerageRecordPageReqVO reqVO = new TradeBrokerageRecordPageReqVO(); + BrokerageRecordPageReqVO reqVO = new BrokerageRecordPageReqVO(); reqVO.setUserId(null); reqVO.setBizType(null); reqVO.setStatus(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = tradeBrokerageRecordService.getBrokerageRecordPage(reqVO); + PageResult pageResult = brokerageRecordService.getBrokerageRecordPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); @@ -79,38 +79,38 @@ public class TradeBrokerageRecordServiceImplTest extends BaseDbUnitTest { } @Test - public void testCalculateBrokerage_useSkuBrokeragePrice() { + public void testCalculatePrice_useFixedPrice() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); - Integer skuBrokeragePrice = randomInt(); + Integer fixedPrice = randomInt(); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 - assertEquals(brokerage, skuBrokeragePrice); + assertEquals(brokerage, fixedPrice); } @Test - public void testCalculateBrokerage_usePercent() { + public void testCalculatePrice_usePercent() { // mock 数据 Integer payPrice = randomInteger(); Integer percent = randomInt(1, 101); - Integer skuBrokeragePrice = randomEle(new Integer[]{0, null}); - System.out.println("skuBrokeragePrice=" + skuBrokeragePrice); + Integer fixedPrice = randomEle(new Integer[]{0, null}); + System.out.println("fixedPrice=" + fixedPrice); // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 assertEquals(brokerage, NumberUtil.div(NumberUtil.mul(payPrice, percent), 100, 0, RoundingMode.DOWN).intValue()); } @Test - public void testCalculateBrokerage_equalsZero() { + public void testCalculatePrice_equalsZero() { // mock 数据 Integer payPrice = null; Integer percent = null; - Integer skuBrokeragePrice = null; + Integer fixedPrice = null; // 调用 - int brokerage = tradeBrokerageRecordService.calculateBrokerage(payPrice, percent, skuBrokeragePrice); + int brokerage = brokerageRecordService.calculatePrice(payPrice, percent, fixedPrice); // 断言 assertEquals(brokerage, 0); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java similarity index 70% rename from yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java rename to yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java index 153bbb426..1c505e1b4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/TradeBrokerageUserServiceImplTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImplTest.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.TradeBrokerageUserPageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.TradeBrokerageUserDO; -import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.TradeBrokerageUserMapper; +import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; +import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -19,43 +19,43 @@ import static org.junit.jupiter.api.Assertions.assertEquals; // TODO @芋艿:单测后续看看 /** - * {@link TradeBrokerageUserServiceImpl} 的单元测试类 + * {@link BrokerageUserServiceImpl} 的单元测试类 * * @author owen */ -@Import(TradeBrokerageUserServiceImpl.class) -public class TradeBrokerageUserServiceImplTest extends BaseDbUnitTest { +@Import(BrokerageUserServiceImpl.class) +public class BrokerageUserServiceImplTest extends BaseDbUnitTest { @Resource - private TradeBrokerageUserServiceImpl brokerageUserService; + private BrokerageUserServiceImpl brokerageUserService; @Resource - private TradeBrokerageUserMapper brokerageUserMapper; + private BrokerageUserMapper brokerageUserMapper; @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetBrokerageUserPage() { // mock 数据 - TradeBrokerageUserDO dbBrokerageUser = randomPojo(TradeBrokerageUserDO.class, o -> { // 等会查询到 - o.setBrokerageUserId(null); + BrokerageUserDO dbBrokerageUser = randomPojo(BrokerageUserDO.class, o -> { // 等会查询到 + o.setBindUserId(null); o.setBrokerageEnabled(null); o.setCreateTime(null); }); brokerageUserMapper.insert(dbBrokerageUser); // 测试 brokerageUserId 不匹配 - brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageUserId(null))); + brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBindUserId(null))); // 测试 brokerageEnabled 不匹配 brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setBrokerageEnabled(null))); // 测试 createTime 不匹配 brokerageUserMapper.insert(cloneIgnoreId(dbBrokerageUser, o -> o.setCreateTime(null))); // 准备参数 - TradeBrokerageUserPageReqVO reqVO = new TradeBrokerageUserPageReqVO(); - reqVO.setBrokerageUserId(null); + BrokerageUserPageReqVO reqVO = new BrokerageUserPageReqVO(); + reqVO.setBindUserId(null); reqVO.setBrokerageEnabled(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = brokerageUserService.getBrokerageUserPage(reqVO); + PageResult pageResult = brokerageUserService.getBrokerageUserPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index 02045d2c2..4c0e0fcea 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -128,19 +128,19 @@ CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( CREATE TABLE IF NOT EXISTS "trade_brokerage_user" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "brokerage_user_id" bigint NOT NULL, - "brokerage_bind_time" varchar, - "brokerage_enabled" bit NOT NULL, - "brokerage_time" varchar, - "brokerage_price" int NOT NULL, - "frozen_brokerage_price" int NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - "tenant_id" bigint NOT NULL DEFAULT '0', + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "bind_user_id" bigint NOT NULL, + "bind_user_time" varchar, + "brokerage_enabled" bit NOT NULL, + "brokerage_time" varchar, + "price" int NOT NULL, + "frozen_price" int NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT '0', PRIMARY KEY ("id") ) COMMENT '分销用户'; CREATE TABLE IF NOT EXISTS "trade_brokerage_record" diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index dc7a58770..cf375f4e4 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -13,7 +13,6 @@ public interface ErrorCodeConstants { ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); - ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足"); // ========== AUTH 模块 1004003000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index a5eda05b0..1df7e7be8 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -33,6 +33,11 @@ yudao-module-infra-api ${revision} + + cn.iocoder.boot + yudao-module-trade-api + ${revision} + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index 4d15aad1f..461a1a5c5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import cn.iocoder.yudao.module.trade.api.brokerage.BrokerageApi; +import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.Optional; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -33,14 +36,18 @@ public class AppMemberUserController { @Resource private MemberLevelService levelService; + @Resource + private BrokerageApi brokerageApi; + @GetMapping("/get") @Operation(summary = "获得基本信息") @PreAuthenticated public CommonResult getUserInfo() { MemberUserDO user = userService.getUser(getLoginUserId()); MemberLevelDO level = levelService.getLevel(user.getLevelId()); + BrokerageUserDTO brokerageUser = brokerageApi.getBrokerageUser(user.getId()); return success(MemberUserConvert.INSTANCE.convert(user, level) - .setBrokerageEnabled(true) // TODO @疯狂:这里我先写死,后面改成 db 返回; + .setBrokerageEnabled(Optional.ofNullable(brokerageUser).map(BrokerageUserDTO::getBrokerageEnabled).orElse(false)) ); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java index 242cb7110..520d5a7d1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/MemberUserDO.java @@ -136,38 +136,4 @@ public class MemberUserDO extends TenantBaseDO { */ private Long groupId; - // TODO @疯狂:看看要不要删除掉哈 - // ========== 分销相关 ========== - - /** - * 推广员编号 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private Long brokerageUserId; - /** - * 推广员绑定时间 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private LocalDateTime brokerageBindTime; - /** - * 是否成为推广员 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private Boolean brokerageEnabled; - /** - * 成为分销员时间 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private LocalDateTime brokerageTime; - /** - * 可用佣金 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private Integer brokeragePrice; - /** - * 冻结佣金 - */ - @TableField(exist = false) // TODO 芋艿:避免报错 - private Integer frozenBrokeragePrice; - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 2a6750e5d..f172eb187 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -31,7 +32,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; -import cn.iocoder.yudao.module.pay.util.MoneyUtils; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service;