trade:初始化

This commit is contained in:
YunaiV 2023-10-23 09:48:38 +08:00
parent 52f014b195
commit 537d3421a8
305 changed files with 21783 additions and 16 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.common.util.number;
import cn.hutool.core.math.Money;
import cn.hutool.core.util.NumberUtil;
import java.math.BigDecimal;
@ -16,7 +17,7 @@ public class MoneyUtils {
* 计算百分比金额四舍五入
*
* @param price 金额
* @param rate 百分比例如说 56.77% 则传入 56.77
* @param rate 百分比例如说 56.77% 则传入 56.77
* @return 百分比金额
*/
public static Integer calculateRatePrice(Integer price, Double rate) {
@ -27,24 +28,46 @@ public class MoneyUtils {
* 计算百分比金额向下传入
*
* @param price 金额
* @param rate 百分比例如说 56.77% 则传入 56.77
* @param rate 百分比例如说 56.77% 则传入 56.77
* @return 百分比金额
*/
public static Integer calculateRatePriceFloor(Integer price, Double rate) {
return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue();
}
/**
* 计算百分比金额
*
* @param price 金额
* @param rate 百分比例如说 56.77% 则传入 56.77
* @param scale 保留小数位数
* @param roundingMode 舍入模式
*/
public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
.divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
}
/**
* 计算百分比金额
*
* @param price 金额
* @param rate 百分比例如说 56.77% 则传入 56.77
* @param scale 保留小数位数
* @param roundingMode 舍入模式
*/
public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
.divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
}
/**
* 分转元
*
* @param fen
* @return
*/
public static BigDecimal fenToYuan(int fen) {
return new Money(0, fen).getAmount();
}
/**
* 分转元字符串
*
* 例如说 fen 1 则结果为 0.01
*
* @param fen
* @return
*/
public static String fenToYuanStr(int fen) {
return new Money(0, fen).toString();
}
}

View File

@ -13,4 +13,28 @@ public class NumberUtils {
return StrUtil.isNotEmpty(str) ? Long.valueOf(str) : null;
}
/**
* 通过经纬度获取地球上两点之间的距离
*
* 参考 <<a href="https://gitee.com/dromara/hutool/blob/1caabb586b1f95aec66a21d039c5695df5e0f4c1/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java">DistanceUtil</a>> 实现目前它已经被 hutool 删除
*
* @param lat1 经度1
* @param lng1 纬度1
* @param lat2 经度2
* @param lng2 纬度2
* @return 距离单位千米
*/
public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
double radLat1 = lat1 * Math.PI / 180.0;
double radLat2 = lat2 * Math.PI / 180.0;
double a = radLat1 - radLat2;
double b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
+ Math.cos(radLat1) * Math.cos(radLat2)
* Math.pow(Math.sin(b / 2), 2)));
distance = distance * 6378.137;
distance = Math.round(distance * 10000d) / 10000d;
return distance;
}
}

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.Db;
@ -18,6 +19,9 @@ import java.util.List;
/**
* MyBatis Plus BaseMapper 的基础上拓展提供更多的能力
*
* 1. {@link BaseMapper} MyBatis Plus 的基础接口提供基础的 CRUD 能力
* 2. {@link MPJBaseMapper} MyBatis Plus Join 的基础接口提供连表 Join 能力
*/
public interface BaseMapperX<T> extends MPJBaseMapper<T> {
@ -45,8 +49,14 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3));
}
default Long selectCount() {
return selectCount(new QueryWrapper<T>());
return selectCount(new QueryWrapper<>());
}
default Long selectCount(String field, Object value) {

View File

@ -0,0 +1,313 @@
package cn.iocoder.yudao.framework.mybatis.core.query;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.function.Consumer;
/**
* 拓展 MyBatis Plus Join QueryWrapper 主要增加如下功能
* <p>
* 1. 拼接条件的方法增加 xxxIfPresent 方法用于判断值不存在的时候不要拼接到条件中
*
* @param <T> 数据类型
*/
public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
public MPJLambdaWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {
MPJWrappers.lambdaJoin().like(column, val);
if (StringUtils.hasText(val)) {
return (MPJLambdaWrapperX<T>) super.like(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
return (MPJLambdaWrapperX<T>) super.in(column, values);
}
return this;
}
public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
return (MPJLambdaWrapperX<T>) super.in(column, values);
}
return this;
}
public MPJLambdaWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {
if (ObjectUtil.isNotEmpty(val)) {
return (MPJLambdaWrapperX<T>) super.eq(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {
if (ObjectUtil.isNotEmpty(val)) {
return (MPJLambdaWrapperX<T>) super.ne(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.gt(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.ge(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.lt(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.le(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {
if (val1 != null && val2 != null) {
return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null) {
return (MPJLambdaWrapperX<T>) ge(column, val1);
}
if (val2 != null) {
return (MPJLambdaWrapperX<T>) le(column, val2);
}
return this;
}
public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
Object val1 = ArrayUtils.get(values, 0);
Object val2 = ArrayUtils.get(values, 1);
return betweenIfPresent(column, val1, val2);
}
// ========== 重写父类方法方便链式调用 ==========
@Override
public <X> MPJLambdaWrapperX<T> eq(boolean condition, SFunction<X, ?> column, Object val) {
super.eq(condition, column, val);
return this;
}
@Override
public <X> MPJLambdaWrapperX<T> eq(SFunction<X, ?> column, Object val) {
super.eq(column, val);
return this;
}
@Override
public <X> MPJLambdaWrapperX<T> orderByDesc(SFunction<X, ?> column) {
//noinspection unchecked
super.orderByDesc(true, column);
return this;
}
@Override
public MPJLambdaWrapperX<T> last(String lastSql) {
super.last(lastSql);
return this;
}
@Override
public <X> MPJLambdaWrapperX<T> in(SFunction<X, ?> column, Collection<?> coll) {
super.in(column, coll);
return this;
}
@Override
public MPJLambdaWrapperX<T> selectAll(Class<?> clazz) {
super.selectAll(clazz);
return this;
}
@Override
public MPJLambdaWrapperX<T> selectAll(Class<?> clazz, String prefix) {
super.selectAll(clazz, prefix);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, String alias) {
super.selectAs(column, alias);
return this;
}
@Override
public <E> MPJLambdaWrapperX<T> selectAs(String column, SFunction<E, ?> alias) {
super.selectAs(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectAs(column, alias);
return this;
}
@Override
public <E, X> MPJLambdaWrapperX<T> selectAs(String index, SFunction<E, ?> column, SFunction<X, ?> alias) {
super.selectAs(index, column, alias);
return this;
}
@Override
public <E> MPJLambdaWrapperX<T> selectAsClass(Class<E> source, Class<?> tag) {
super.selectAsClass(source, tag);
return this;
}
@Override
public <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {
super.selectSub(clazz, consumer, alias);
return this;
}
@Override
public <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, String st, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {
super.selectSub(clazz, st, consumer, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column) {
super.selectCount(column);
return this;
}
@Override
public MPJLambdaWrapperX<T> selectCount(Object column, String alias) {
super.selectCount(column, alias);
return this;
}
@Override
public <X> MPJLambdaWrapperX<T> selectCount(Object column, SFunction<X, ?> alias) {
super.selectCount(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, String alias) {
super.selectCount(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectCount(column, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column) {
super.selectSum(column);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, String alias) {
super.selectSum(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectSum(column, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column) {
super.selectMax(column);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, String alias) {
super.selectMax(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectMax(column, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column) {
super.selectMin(column);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, String alias) {
super.selectMin(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectMin(column, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column) {
super.selectAvg(column);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, String alias) {
super.selectAvg(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectAvg(column, alias);
return this;
}
@Override
public <S> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column) {
super.selectLen(column);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, String alias) {
super.selectLen(column, alias);
return this;
}
@Override
public <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, SFunction<X, ?> alias) {
super.selectLen(column, alias);
return this;
}
}

View File

@ -23,7 +23,7 @@
<module>yudao-module-product-api</module>
<module>yudao-module-product-biz</module>
<module>yudao-module-trade-api</module>
<!-- <module>yudao-module-trade-biz</module>-->
<module>yudao-module-trade-biz</module>
<!-- <module>yudao-module-statistics-api</module>-->
<!-- <module>yudao-module-statistics-biz</module>-->
</modules>

View File

@ -0,0 +1,19 @@
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
## 感谢复旦核博士的建议!灰子哥,牛皮!
FROM eclipse-temurin:8-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /yudao-module-trade-biz
WORKDIR /yudao-module-trade-biz
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/yudao-module-trade-biz.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m"
## 暴露后端项目的 48080 端口
EXPOSE 48102
## 启动后端项目
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-trade-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
trade 模块,主要实现交易相关功能
例如:订单、退款、购物车等功能。
</description>
<dependencies>
<!-- Spring Cloud 基础 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-env</artifactId>
</dependency>
<!-- 依赖服务 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-trade-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-product-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-pay-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-promotion-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-member-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- TODO 芋艿:引入依赖要优化下: -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Config 配置中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Job 定时任务相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-job</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.trade;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 项目的启动类
*
* 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
* 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
* 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
*
* @author 芋道源码
*/
@SpringBootApplication
public class TradeServerApplication {
public static void main(String[] args) {
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
SpringApplication.run(TradeServerApplication.class, args);
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.trade.api.order;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
/**
* 订单 API 接口实现类
*
* @author HUIHUI
*/
@Service
@Validated
public class TradeOrderApiImpl implements TradeOrderApi {
@Resource
private TradeOrderUpdateService tradeOrderUpdateService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Override
public List<TradeOrderRespDTO> getOrderList(Collection<Long> ids) {
return TradeOrderConvert.INSTANCE.convertList04(tradeOrderQueryService.getOrderList(ids));
}
@Override
public TradeOrderRespDTO getOrder(Long id) {
return TradeOrderConvert.INSTANCE.convert(tradeOrderQueryService.getOrder(id));
}
@Override
public void cancelPaidOrder(Long userId, Long orderId) {
tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.yudao.module.trade.api;

View File

@ -0,0 +1,146 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*;
import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService;
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
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.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 售后订单")
@RestController
@RequestMapping("/trade/after-sale")
@Validated
@Slf4j
public class AfterSaleController {
@Resource
private AfterSaleService afterSaleService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private AfterSaleLogService afterSaleLogService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/page")
@Operation(summary = "获得售后订单分页")
@PreAuthorize("@ss.hasPermission('trade:after-sale:query')")
public CommonResult<PageResult<AfterSaleRespPageItemVO>> getAfterSalePage(@Valid AfterSalePageReqVO pageVO) {
// 查询售后
PageResult<AfterSaleDO> pageResult = afterSaleService.getAfterSalePage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty());
}
// 查询会员
Map<Long, MemberUserRespDTO> memberUsers = memberUserApi.getUserMap(
convertSet(pageResult.getList(), AfterSaleDO::getUserId));
return success(AfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers));
}
@GetMapping("/get-detail")
@Operation(summary = "获得售后订单详情")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:after-sale:query')")
public CommonResult<AfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
AfterSaleDO afterSale = afterSaleService.getAfterSale(id);
if (afterSale == null) {
return success(null);
}
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());
// 查询订单项
TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(afterSale.getOrderItemId());
// 拼接数据
MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()).getCheckedData();
List<AfterSaleLogDO> logs = afterSaleLogService.getAfterSaleLogList(afterSale.getId());
return success(AfterSaleConvert.INSTANCE.convert(afterSale, order, orderItem, user, logs));
}
@PutMapping("/agree")
@Operation(summary = "同意售后")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:after-sale:agree')")
public CommonResult<Boolean> agreeAfterSale(@RequestParam("id") Long id) {
afterSaleService.agreeAfterSale(getLoginUserId(), id);
return success(true);
}
@PutMapping("/disagree")
@Operation(summary = "拒绝售后")
@PreAuthorize("@ss.hasPermission('trade:after-sale:disagree')")
public CommonResult<Boolean> disagreeAfterSale(@RequestBody AfterSaleDisagreeReqVO confirmReqVO) {
afterSaleService.disagreeAfterSale(getLoginUserId(), confirmReqVO);
return success(true);
}
@PutMapping("/receive")
@Operation(summary = "确认收货")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:after-sale:receive')")
public CommonResult<Boolean> receiveAfterSale(@RequestParam("id") Long id) {
afterSaleService.receiveAfterSale(getLoginUserId(), id);
return success(true);
}
@PutMapping("/refuse")
@Operation(summary = "拒绝收货")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:after-sale:receive')")
public CommonResult<Boolean> refuseAfterSale(AfterSaleRefuseReqVO refuseReqVO) {
afterSaleService.refuseAfterSale(getLoginUserId(), refuseReqVO);
return success(true);
}
@PutMapping("/refund")
@Operation(summary = "确认退款")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:after-sale:refund')")
public CommonResult<Boolean> refundAfterSale(@RequestParam("id") Long id) {
afterSaleService.refundAfterSale(getLoginUserId(), getClientIP(), id);
return success(true);
}
@PostMapping("/update-refunded")
@Operation(summary = "更新售后订单为已退款") // pay-module 支付服务进行回调可见 PayNotifyJob
@PermitAll // 无需登录安全由 PayDemoOrderService 内部校验实现
@OperateLog(enable = false) // 禁用操作日志因为没有操作人
public CommonResult<Boolean> updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
// 目前业务逻辑不需要做任何事情
// 当然退款会有小概率会失败的情况可以监控失败状态进行告警
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
return success(true);
}
}

View File

@ -0,0 +1,33 @@
### 获得交易售后分页 => 成功
GET {{baseUrl}}/trade/after-sale/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 同意售后 => 成功
PUT {{baseUrl}}/trade/after-sale/agree?id=7
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
### 拒绝售后 => 成功
PUT {{baseUrl}}/trade/after-sale/disagree
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
{
"id": 6,
"auditReason": "阿巴巴"
}
### 确认退款 => 成功
PUT {{baseUrl}}/trade/after-sale/refund?id=6
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json
### 确认收货 => 成功
PUT {{baseUrl}}/trade/after-sale/receive?id=7
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
Content-Type: application/json

View File

@ -0,0 +1,119 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 交易售后 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class AfterSaleBaseVO {
@Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202211190847450020500077")
@NotNull(message = "售后流水号不能为空")
private String no;
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后状态不能为空")
private Integer status;
@Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
@NotNull(message = "售后类型不能为空")
private Integer type;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后方式不能为空")
private Integer way;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30337")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢")
@NotNull(message = "申请原因不能为空")
private String applyReason;
@Schema(description = "补充描述", example = "你说的对")
private String applyDescription;
@Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png")
private List<String> applyPicUrls;
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18078")
@NotNull(message = "订单编号不能为空")
private Long orderId;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022111917190001")
@NotNull(message = "订单流水号不能为空")
private String orderNo;
@Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "572")
@NotNull(message = "订单项编号不能为空")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2888")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "商品 SPU 名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15657")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "商品图片", example = "https://www.iocoder.cn/2.png")
private String picUrl;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20012")
@NotNull(message = "购买数量不能为空")
private Integer count;
@Schema(description = "审批时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime auditTime;
@Schema(description = "审批人", example = "30835")
private Long auditUserId;
@Schema(description = "审批备注", example = "不香")
private String auditReason;
@Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "18077")
@NotNull(message = "退款金额,单位:分不能为空")
private Integer refundPrice;
@Schema(description = "支付退款编号", example = "10271")
private Long payRefundId;
@Schema(description = "退款时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime refundTime;
@Schema(description = "退货物流公司编号", example = "10")
private Long logisticsId;
@Schema(description = "退货物流单号", example = "610003952009")
private String logisticsNo;
@Schema(description = "退货时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime receiveTime;
@Schema(description = "收货备注", example = "不喜欢")
private String receiveReason;
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderItemBaseVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 售后订单的详情 Response VO")
@Data
public class AfterSaleDetailRespVO extends AfterSaleBaseVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
/**
* 订单基本信息
*/
private TradeOrderBaseVO order;
/**
* 订单项列表
*/
private OrderItem orderItem;
/**
* 用户信息
*/
private MemberUserRespVO user;
/**
* 售后日志
*/
private List<AfterSaleLogRespVO> logs;
@Schema(description = "管理后台 - 交易订单的详情的订单项目")
@Data
public static class OrderItem extends TradeOrderItemBaseVO {
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
}
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 交易售后拒绝 Request VO")
@Data
public class AfterSaleDisagreeReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "审批备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotEmpty(message = "审批备注不能为空")
private String auditReason;
}

View File

@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易售后分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AfterSalePageReqVO extends PageParam {
@Schema(description = "售后流水号", example = "202211190847450020500077")
private String no;
@Schema(description = "售后状态", example = "10")
@InEnum(value = AfterSaleStatusEnum.class, message = "售后状态必须是 {value}")
private Integer status;
@Schema(description = "售后类型", example = "20")
@InEnum(value = AfterSaleTypeEnum.class, message = "售后类型必须是 {value}")
private Integer type;
@Schema(description = "售后方式", example = "10")
@InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
private Integer way;
@Schema(description = "订单编号", example = "18078")
private String orderNo;
@Schema(description = "商品 SPU 名称", example = "李四")
private String spuName;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 交易售后拒绝收货 Request VO")
@Data
public class AfterSaleRefuseReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "收货备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotNull(message = "收货备注不能为空")
private String refuseMemo;
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 交易售后分页的每一条记录 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AfterSaleRespPageItemVO extends AfterSaleBaseVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27630")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
/**
* 商品属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
/**
* 用户信息
*/
private MemberUserRespVO user;
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 交易售后日志 Response VO")
@Data
public class AfterSaleLogRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669")
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "用户类型不能为空")
private Integer userType;
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023")
@NotNull(message = "售后编号不能为空")
private Long afterSaleId;
@Schema(description = "售后状态(之前)", example = "2")
private Integer beforeStatus;
@Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "售后状态(之后)不能为空")
private Integer afterStatus;
@Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成退款金额¥37776.00")
@NotNull(message = "操作明细不能为空")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,4 @@
/**
* 占位符可忽略
*/
package cn.iocoder.yudao.module.trade.controller.admin.base.member;

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.trade.controller.admin.base.member.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 会员用户 Response VO")
@Data
public class MemberUserRespVO {
@Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String nickname;
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
private String avatar;
}

View File

@ -0,0 +1,4 @@
/**
* 放置该模块通用的 VO
*/
package cn.iocoder.yudao.module.trade.controller.admin.base;

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.base.product.property;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 商品属性值的明细 Response VO")
@Data
public class ProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage;
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.vo.record.BrokerageRecordPageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordRespVO;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
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.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
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.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 佣金记录")
@RestController
@RequestMapping("/trade/brokerage-record")
@Validated
public class BrokerageRecordController {
@Resource
private BrokerageRecordService brokerageRecordService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/get")
@Operation(summary = "获得佣金记录")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')")
public CommonResult<BrokerageRecordRespVO> 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<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) {
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO);
// 查询用户信息
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId);
userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId));
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 拼接数据
return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap));
}
}

View File

@ -0,0 +1,111 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage;
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.vo.user.*;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.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.enums.brokerage.BrokerageWithdrawStatusEnum;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
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 BrokerageWithdrawService brokerageWithdrawService;
@Resource
private MemberUserApi memberUserApi;
@PutMapping("/update-bind-user")
@Operation(summary = "修改推广员")
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-bind-user')")
public CommonResult<Boolean> updateBindUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) {
brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId());
return success(true);
}
@PutMapping("/clear-bind-user")
@Operation(summary = "清除推广员")
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-bind-user')")
public CommonResult<Boolean> clearBindUser(@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<Boolean> updateBrokerageEnabled(@Valid @RequestBody BrokerageUserUpdateBrokerageEnabledReqVO updateReqVO) {
brokerageUserService.updateBrokerageUserEnabled(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<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) {
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id);
BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser);
return success(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id).getCheckedData(), respVO));
}
@GetMapping("/page")
@Operation(summary = "获得分销用户分页")
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')")
public CommonResult<PageResult<BrokerageUserRespVO>> getBrokerageUserPage(@Valid BrokerageUserPageReqVO pageVO) {
// 分页查询
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(pageVO);
// 查询用户信息
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 合计分佣的推广订单
Map<Long, UserBrokerageSummaryRespBO> brokerageOrderSummaryMap = brokerageRecordService.getUserBrokerageSummaryMapByUserId(
userIds, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
// 合计分佣的推广用户
// TODO @疯狂转成 map 批量读取
Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
userId -> userId,
userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
// 合计分佣的提现
// TODO @疯狂如果未来支持了打款这个动作可能 status 会不对
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(
userIds, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
// 拼接返回
return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
brokerageOrderSummaryMap, withdrawMap));
}
}

View File

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

View File

@ -0,0 +1,65 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 佣金记录 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class BrokerageRecordBaseVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25973")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23353")
@NotEmpty(message = "业务编号不能为空")
private String bizId;
@Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "业务类型不能为空")
private Integer bizType;
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "标题不能为空")
private String title;
@Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "28731")
@NotNull(message = "金额不能为空")
private Integer price;
@Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "13226")
@NotNull(message = "当前总佣金不能为空")
private Integer totalPrice;
@Schema(description = "说明", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
@NotNull(message = "说明不能为空")
private String description;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
@Schema(description = "冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "冻结时间(天)不能为空")
private Integer frozenDays;
@Schema(description = "解冻时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime unfreezeTime;
@Schema(description = "来源用户等级")
private Integer sourceUserLevel;
@Schema(description = "来源用户编号")
private Long sourceUserId;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 佣金记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageRecordPageReqVO extends PageParam {
@Schema(description = "用户编号", example = "25973")
private Long userId;
@Schema(description = "业务类型", example = "1")
private Integer bizType;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "用户类型", example = "1")
private Integer sourceUserLevel;
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record;
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 BrokerageRecordRespVO extends BrokerageRecordBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28896")
private Integer id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
// ========== 用户信息 ==========
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
private String userAvatar;
@Schema(description = "用户昵称", example = "李四")
private String userNickname;
// ========== 来源用户信息 ==========
@Schema(description = "来源用户头像", example = "https://www.iocoder.cn/xxx.png")
private String sourceUserAvatar;
@Schema(description = "来源用户昵称", example = "李四")
private String sourceUserNickname;
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 分销用户 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class BrokerageUserBaseVO {
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
@NotNull(message = "推广员编号不能为空")
private Long bindUserId;
@Schema(description = "推广员绑定时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime bindUserTime;
@Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "推广资格不能为空")
private Boolean brokerageEnabled;
@Schema(description = "成为分销员时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime brokerageTime;
@Schema(description = "可用佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "11089")
@NotNull(message = "可用佣金不能为空")
private Integer price;
@Schema(description = "冻结佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "30916")
@NotNull(message = "冻结佣金不能为空")
private Integer frozenPrice;
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 分销用户 - 清除推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserClearBrokerageUserReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 分销用户分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BrokerageUserPageReqVO extends PageParam {
@Schema(description = "推广员编号", example = "4587")
private Long bindUserId;
@Schema(description = "推广资格", example = "true")
private Boolean brokerageEnabled;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "用户等级", example = "1") // 注意这了不是用户的会员等级而是过滤推广的层级
private Integer level;
@Schema(description = "绑定时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] bindUserTime;
}

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
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 = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.png")
private String avatar;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String nickname;
// ========== 推广信息 ========== 注意是包括 1 + 2 级的数据
@Schema(description = "推广用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageUserCount;
@Schema(description = "推广订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageOrderCount;
@Schema(description = "推广订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer brokerageOrderPrice;
// ========== 提现信息 ==========
@Schema(description = "已提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer withdrawPrice;
@Schema(description = "已提现次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
private Integer withdrawCount;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserUpdateBrokerageEnabledReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
@Schema(description = "推广资格", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "推广资格不能为空")
private Boolean enabled;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 分销用户 - 修改推广员 Request VO")
@Data
@ToString(callSuper = true)
public class BrokerageUserUpdateBrokerageUserReqVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
@NotNull(message = "用户编号不能为空")
private Long id;
@Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4587")
@NotNull(message = "推广员编号不能为空")
private Long bindUserId;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.trade.controller.admin.config;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.config.vo.TradeConfigSaveReqVO;
import cn.iocoder.yudao.module.trade.convert.config.TradeConfigConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
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/config")
@Validated
public class TradeConfigController {
@Resource
private TradeConfigService tradeConfigService;
@Value("${yudao.tencent-lbs-key}")
private String tencentLbsKey;
@PutMapping("/save")
@Operation(summary = "更新交易中心配置")
@PreAuthorize("@ss.hasPermission('trade:config:save')")
public CommonResult<Boolean> updateConfig(@Valid @RequestBody TradeConfigSaveReqVO updateReqVO) {
tradeConfigService.saveTradeConfig(updateReqVO);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得交易中心配置")
@PreAuthorize("@ss.hasPermission('trade:config:query')")
public CommonResult<TradeConfigRespVO> getConfig() {
TradeConfigDO config = tradeConfigService.getTradeConfig();
TradeConfigRespVO configVO = TradeConfigConvert.INSTANCE.convert(config);
if (configVO != null) {
configVO.setTencentLbsKey(tencentLbsKey);
}
return success(configVO);
}
}

View File

@ -0,0 +1,104 @@
package cn.iocoder.yudao.module.trade.controller.admin.config.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
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.Range;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import java.util.List;
/**
* 交易中心配置 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class TradeConfigBaseVO {
// ========== 售后相关 ==========
@Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "售后的退款理由不能为空")
private List<String> afterSaleRefundReasons;
@Schema(description = "售后的退货理由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "售后的退货理由不能为空")
private List<String> afterSaleReturnReasons;
// ========== 配送相关 ==========
/**
* 是否启用全场包邮
*/
@Schema(description = "是否启用全场包邮", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否启用全场包邮不能为空")
private Boolean deliveryExpressFreeEnabled;
@Schema(description = "全场包邮的最小金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "全场包邮的最小金额不能为空")
@PositiveOrZero(message = "全场包邮的最小金额不能是负数")
private Integer deliveryExpressFreePrice;
@Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否开启自提不能为空")
private Boolean deliveryPickUpEnabled;
// ========== 分销相关 ==========
@Schema(description = "是否启用分佣", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否启用分佣不能为空")
private Boolean brokerageEnabled;
@Schema(description = "分佣模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "分佣模式不能为空")
@InEnum(value = BrokerageEnabledConditionEnum.class, message = "分佣模式必须是 {value}")
private Integer brokerageEnabledCondition;
@Schema(description = "分销关系绑定模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "分销关系绑定模式不能为空")
@InEnum(value = BrokerageBindModeEnum.class, message = "分销关系绑定模式必须是 {value}")
private Integer brokerageBindMode;
@Schema(description = "分销海报图地址数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/yudao.jpg]")
private List<String> brokeragePosterUrls;
@Schema(description = "一级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "一级返佣比例不能为空")
@Range(min = 0, max = 100, message = "一级返佣比例必须在 0 - 100 之间")
private Integer brokerageFirstPercent;
@Schema(description = "二级返佣比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "二级返佣比例不能为空")
@Range(min = 0, max = 100, message = "二级返佣比例必须在 0 - 100 之间")
private Integer brokerageSecondPercent;
@Schema(description = "用户提现最低金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "用户提现最低金额不能为空")
@PositiveOrZero(message = "用户提现最低金额不能是负数")
private Integer brokerageWithdrawMinPrice;
@Schema(description = "用户提现手续费百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "用户提现手续费百分比不能为空")
@PositiveOrZero(message = "用户提现手续费百分比不能是负数")
private Integer brokerageWithdrawFeePercent;
@Schema(description = "提现银行", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
@NotEmpty(message = "提现银行不能为空")
private List<Integer> brokerageBankNames;
@Schema(description = "佣金冻结时间(天)", requiredMode = Schema.RequiredMode.REQUIRED, example = "7")
@NotNull(message = "佣金冻结时间(天)不能为空")
@PositiveOrZero(message = "佣金冻结时间不能是负数")
private Integer brokerageFrozenDays;
@Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
@NotEmpty(message = "提现方式不能为空")
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}")
private List<Integer> brokerageWithdrawTypes;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.trade.controller.admin.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 交易中心配置 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TradeConfigRespVO extends TradeConfigBaseVO {
@Schema(description = "自增主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String tencentLbsKey;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.trade.controller.admin.config.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 交易中心配置更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TradeConfigSaveReqVO extends TradeConfigBaseVO {
}

View File

@ -0,0 +1,96 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.*;
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
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.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 快递公司")
@RestController
@RequestMapping("/trade/delivery/express")
@Validated
public class DeliveryExpressController {
@Resource
private DeliveryExpressService deliveryExpressService;
@PostMapping("/create")
@Operation(summary = "创建快递公司")
@PreAuthorize("@ss.hasPermission('trade:delivery:express:create')")
public CommonResult<Long> createDeliveryExpress(@Valid @RequestBody DeliveryExpressCreateReqVO createReqVO) {
return success(deliveryExpressService.createDeliveryExpress(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新快递公司")
@PreAuthorize("@ss.hasPermission('trade:delivery:express:update')")
public CommonResult<Boolean> updateDeliveryExpress(@Valid @RequestBody DeliveryExpressUpdateReqVO updateReqVO) {
deliveryExpressService.updateDeliveryExpress(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除快递公司")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('trade:delivery:express:delete')")
public CommonResult<Boolean> deleteDeliveryExpress(@RequestParam("id") Long id) {
deliveryExpressService.deleteDeliveryExpress(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得快递公司")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('trade:delivery:express:query')")
public CommonResult<DeliveryExpressRespVO> getDeliveryExpress(@RequestParam("id") Long id) {
DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(id);
return success(DeliveryExpressConvert.INSTANCE.convert(deliveryExpress));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递公司精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<DeliveryExpressSimpleRespVO>> getSimpleDeliveryExpressList() {
List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressListByStatus(CommonStatusEnum.ENABLE.getStatus());
return success(DeliveryExpressConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得快递公司分页")
@PreAuthorize("@ss.hasPermission('trade:delivery:express:query')")
public CommonResult<PageResult<DeliveryExpressRespVO>> getDeliveryExpressPage(@Valid DeliveryExpressPageReqVO pageVO) {
PageResult<DeliveryExpressDO> pageResult = deliveryExpressService.getDeliveryExpressPage(pageVO);
return success(DeliveryExpressConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@Operation(summary = "导出快递公司 Excel")
@PreAuthorize("@ss.hasPermission('trade:delivery:express:export')")
@OperateLog(type = EXPORT)
public void exportDeliveryExpressExcel(@Valid DeliveryExpressExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressList(exportReqVO);
// 导出 Excel
List<DeliveryExpressExcelVO> dataList = DeliveryExpressConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "快递公司.xls", "数据", DeliveryExpressExcelVO.class, dataList);
}
}

View File

@ -0,0 +1,90 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*;
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
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.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 快递运费模板")
@RestController
@RequestMapping("/trade/delivery/express-template")
@Validated
public class DeliveryExpressTemplateController {
@Resource
private DeliveryExpressTemplateService deliveryExpressTemplateService;
@PostMapping("/create")
@Operation(summary = "创建快递运费模板")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:create')")
public CommonResult<Long> createDeliveryExpressTemplate(@Valid @RequestBody DeliveryExpressTemplateCreateReqVO createReqVO) {
return success(deliveryExpressTemplateService.createDeliveryExpressTemplate(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新快递运费模板")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:update')")
public CommonResult<Boolean> updateDeliveryExpressTemplate(@Valid @RequestBody DeliveryExpressTemplateUpdateReqVO updateReqVO) {
deliveryExpressTemplateService.updateDeliveryExpressTemplate(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除快递运费模板")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:delete')")
public CommonResult<Boolean> deleteDeliveryExpressTemplate(@RequestParam("id") Long id) {
deliveryExpressTemplateService.deleteDeliveryExpressTemplate(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得快递运费模板")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:query')")
public CommonResult<DeliveryExpressTemplateDetailRespVO> getDeliveryExpressTemplate(@RequestParam("id") Long id) {
return success(deliveryExpressTemplateService.getDeliveryExpressTemplate(id));
}
@GetMapping("/list")
@Operation(summary = "获得快递运费模板列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:query')")
public CommonResult<List<DeliveryExpressTemplateRespVO>> getDeliveryExpressTemplateList(@RequestParam("ids") Collection<Long> ids) {
List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(ids);
return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<DeliveryExpressTemplateSimpleRespVO>> getSimpleTemplateList() {
// 获取运费模版列表只要开启状态的
List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList();
// 排序后返回给前端
return success(DeliveryExpressTemplateConvert.INSTANCE.convertList1(list));
}
@GetMapping("/page")
@Operation(summary = "获得快递运费模板分页")
@PreAuthorize("@ss.hasPermission('trade:delivery:express-template:query')")
public CommonResult<PageResult<DeliveryExpressTemplateRespVO>> getDeliveryExpressTemplatePage(@Valid DeliveryExpressTemplatePageReqVO pageVO) {
PageResult<DeliveryExpressTemplateDO> pageResult = deliveryExpressTemplateService.getDeliveryExpressTemplatePage(pageVO);
return success(DeliveryExpressTemplateConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.*;
import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryPickUpStoreConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService;
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.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 自提门店")
@RestController
@RequestMapping("/trade/delivery/pick-up-store")
@Validated
public class DeliveryPickUpStoreController {
@Resource
private DeliveryPickUpStoreService deliveryPickUpStoreService;
@PostMapping("/create")
@Operation(summary = "创建自提门店")
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:create')")
public CommonResult<Long> createDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpStoreCreateReqVO createReqVO) {
return success(deliveryPickUpStoreService.createDeliveryPickUpStore(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新自提门店")
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:update')")
public CommonResult<Boolean> updateDeliveryPickUpStore(@Valid @RequestBody DeliveryPickUpStoreUpdateReqVO updateReqVO) {
deliveryPickUpStoreService.updateDeliveryPickUpStore(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除自提门店")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:delete')")
public CommonResult<Boolean> deleteDeliveryPickUpStore(@RequestParam("id") Long id) {
deliveryPickUpStoreService.deleteDeliveryPickUpStore(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得自提门店")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:query')")
public CommonResult<DeliveryPickUpStoreRespVO> getDeliveryPickUpStore(@RequestParam("id") Long id) {
DeliveryPickUpStoreDO deliveryPickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(id);
return success(DeliveryPickUpStoreConvert.INSTANCE.convert(deliveryPickUpStore));
}
@GetMapping("/list-all-simple")
@Operation(summary = "获得自提门店精简信息列表")
public CommonResult<List<DeliveryPickUpStoreSimpleRespVO>> getSimpleDeliveryPickUpStoreList() {
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
CommonStatusEnum.ENABLE.getStatus());
return success(DeliveryPickUpStoreConvert.INSTANCE.convertList1(list));
}
@GetMapping("/list")
@Operation(summary = "获得自提门店列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:query')")
public CommonResult<List<DeliveryPickUpStoreRespVO>> getDeliveryPickUpStoreList(@RequestParam("ids") Collection<Long> ids) {
List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreList(ids);
return success(DeliveryPickUpStoreConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得自提门店分页")
@PreAuthorize("@ss.hasPermission('trade:delivery:pick-up-store:query')")
public CommonResult<PageResult<DeliveryPickUpStoreRespVO>> getDeliveryPickUpStorePage(@Valid DeliveryPickUpStorePageReqVO pageVO) {
PageResult<DeliveryPickUpStoreDO> pageResult = deliveryPickUpStoreService.getDeliveryPickUpStorePage(pageVO);
return success(DeliveryPickUpStoreConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 快递公司 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class DeliveryExpressBaseVO {
@Schema(description = "快递公司编码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "快递公司编码不能为空")
private String code;
@Schema(description = "快递公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "快递公司名称不能为空")
private String name;
@Schema(description = "快递公司logo")
private String logo;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "管理后台 - 快递公司创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressCreateReqVO extends DeliveryExpressBaseVO {
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 快递公司 Excel VO
*/
@Data
public class DeliveryExpressExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("快递公司编码")
private String code;
@ExcelProperty("快递公司名称")
private String name;
@ExcelProperty("快递公司 logo")
private String logo;
@ExcelProperty("排序")
private Integer sort;
@ExcelProperty(value = "状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递公司 Excel 导出 Request VO")
@Data
public class DeliveryExpressExportReqVO {
@Schema(description = "快递公司编码")
private String code;
@Schema(description = "快递公司名称", example = "李四")
private String name;
@Schema(description = "状态0正常 1停用", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递公司分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressPageReqVO extends PageParam {
@Schema(description = "快递公司编码")
private String code;
@Schema(description = "快递公司名称", example = "李四")
private String name;
@Schema(description = "状态0正常 1停用", example = "1")
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
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 DeliveryExpressRespVO extends DeliveryExpressBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 快递公司精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryExpressSimpleRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "快递公司名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "顺丰速运")
@NotNull(message = "快递公司名称不能为空")
private String name;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 快递公司更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressUpdateReqVO extends DeliveryExpressBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6592")
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 快递运费模板 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class DeliveryExpressTemplateBaseVO {
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@NotNull(message = "模板名称不能为空")
private String name;
@Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "配送计费方式 1:按件 2:按重量 3:按体积不能为空")
private Integer chargeMode;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "排序不能为空")
private Integer sort;
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 快递运费模板运费设置 Base VO提供给添加运费模板使用
*/
@Data
public class DeliveryExpressTemplateChargeBaseVO {
@Schema(description = "编号", example = "6592", hidden = true) // 由于想简单一点复用这个 VO 在更新操作所以 hidden false
private Long id;
@Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]")
@NotEmpty(message = "区域编号列表不能为空")
private List<Integer> areaIds;
@Schema(description = "首件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "首件数量不能为空")
private Double startCount;
@Schema(description = "起步价", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "起步价不能为空")
private Integer startPrice;
@Schema(description = "续件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "续件数量不能为空")
private Double extraCount;
@Schema(description = "额外价", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@NotNull(message = "额外价不能为空")
private Integer extraPrice;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateCreateReqVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "区域运费列表")
@Valid
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "包邮区域列表")
@Valid
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板的详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateDetailRespVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
private Long id;
@Schema(description = "运费模板运费设置", requiredMode = Schema.RequiredMode.REQUIRED)
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "运费模板包邮区域", requiredMode = Schema.RequiredMode.REQUIRED)
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 快递运费模板包邮 Base VO提供给添加运费模板使用
*/
@Data
public class DeliveryExpressTemplateFreeBaseVO {
@Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]")
@NotEmpty(message = "区域编号列表不能为空")
private List<Integer> areaIds;
@Schema(description = "包邮金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "5000")
@NotNull(message = "包邮金额不能为空")
private Integer freePrice;
@Schema(description = "包邮件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "包邮件数不能为空")
private Integer freeCount;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 快递运费模板分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplatePageReqVO extends PageParam {
@Schema(description = "模板名称", example = "王五")
private String name;
@Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积")
private Integer chargeMode;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
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 DeliveryExpressTemplateRespVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号,自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 模版精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryExpressTemplateSimpleRespVO {
@Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版")
private String name;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 快递运费模板更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryExpressTemplateUpdateReqVO extends DeliveryExpressTemplateBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "371")
@NotNull(message = "编号不能为空")
private Long id;
@Schema(description = "区域运费列表")
@Valid
private List<DeliveryExpressTemplateChargeBaseVO> charges;
@Schema(description = "包邮区域列表")
@Valid
private List<DeliveryExpressTemplateFreeBaseVO> frees;
}

View File

@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalTime;
/**
* 自提门店 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class DeliveryPickUpStoreBaseVO {
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotBlank(message = "门店名称不能为空")
private String name;
@Schema(description = "门店简介", example = "我是门店简介")
private String introduction;
@Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
@NotBlank(message = "门店手机不能为空")
@Mobile
private String phone;
@Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
@NotNull(message = "区域编号不能为空")
private Integer areaId;
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
@NotBlank(message = "门店详细地址不能为空")
private String detailAddress;
@Schema(description = "门店 logo", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotBlank(message = "门店 logo 不能为空")
private String logo;
@Schema(description = "营业开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "营业开始时间不能为空")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
private LocalTime openingTime;
@Schema(description = "营业结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "营业结束时间不能为空")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
private LocalTime closingTime;
@Schema(description = "纬度", requiredMode = Schema.RequiredMode.REQUIRED, example = "5.88")
@NotNull(message = "纬度不能为空")
private Double latitude;
@Schema(description = "经度", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.99")
@NotNull(message = "经度不能为空")
private Double longitude;
@Schema(description = "门店状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "门店状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 自提门店创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStoreCreateReqVO extends DeliveryPickUpStoreBaseVO {
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import lombok.*;
import java.time.LocalTime;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 自提门店分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStorePageReqVO extends PageParam {
@Schema(description = "门店名称", example = "李四")
private String name;
@Schema(description = "门店手机")
private String phone;
@Schema(description = "区域编号", example = "18733")
private Integer areaId;
@Schema(description = "门店状态", example = "1")
@InEnum(CommonStatusEnum.class)
private Integer status;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
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 DeliveryPickUpStoreRespVO extends DeliveryPickUpStoreBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private Long id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Schema(description = "管理后台 - 自提门店精简信息 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryPickUpStoreSimpleRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
private Long id;
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String name;
@Schema(description = "门店手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601892312")
private String phone;
@Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
private Integer areaId;
@Schema(description = "区域名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xx市")
private String areaName;
@Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
private String detailAddress;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 自提门店更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryPickUpStoreUpdateReqVO extends DeliveryPickUpStoreBaseVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23128")
@NotNull(message = "编号不能为空")
private Long id;
}

View File

@ -0,0 +1,9 @@
### 获得交易订单分页 => 成功
GET {{baseUrl}}/trade/order/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
### 获得交易订单分页 => 成功
GET {{baseUrl}}/trade/order/get-detail?id=21
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}

View File

@ -0,0 +1,168 @@
package cn.iocoder.yudao.module.trade.controller.admin.order;
import cn.hutool.core.collection.CollUtil;
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.order.vo.*;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
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.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - 交易订单")
@RestController
@RequestMapping("/trade/order")
@Validated
@Slf4j
public class TradeOrderController {
@Resource
private TradeOrderUpdateService tradeOrderUpdateService;
@Resource
private TradeOrderQueryService tradeOrderQueryService;
@Resource
private TradeOrderLogService tradeOrderLogService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/page")
@Operation(summary = "获得交易订单分页")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<PageResult<TradeOrderPageItemRespVO>> getOrderPage(TradeOrderPageReqVO reqVO) {
// 查询订单
PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(reqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty());
}
// 查询用户信息
Set<Long> userIds = CollUtil.unionDistinct(convertList(pageResult.getList(), TradeOrderDO::getUserId),
convertList(pageResult.getList(), TradeOrderDO::getBrokerageUserId, Objects::nonNull));
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(
convertSet(pageResult.getList(), TradeOrderDO::getId));
// 最终组合
return success(TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems, userMap));
}
@GetMapping("/summary")
@Operation(summary = "获得交易订单统计")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<TradeOrderSummaryRespVO> getOrderSummary(TradeOrderPageReqVO reqVO) {
return success(tradeOrderQueryService.getOrderSummary(reqVO));
}
@GetMapping("/get-detail")
@Operation(summary = "获得交易订单详情")
@Parameter(name = "id", description = "订单编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(id);
if (order == null) {
return success(null);
}
// 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
// 拼接数据
MemberUserRespDTO user = memberUserApi.getUser(order.getUserId()).getCheckedData();
MemberUserRespDTO brokerageUser = order.getBrokerageUserId() != null ?
memberUserApi.getUser(order.getBrokerageUserId()).getCheckedData() : null;
List<TradeOrderLogDO> orderLogs = tradeOrderLogService.getOrderLogListByOrderId(id);
return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs, user, brokerageUser));
}
@GetMapping("/get-express-track-list")
@Operation(summary = "获得交易订单的物流轨迹")
@Parameter(name = "id", description = "交易订单编号")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) {
return success(TradeOrderConvert.INSTANCE.convertList02(
tradeOrderQueryService.getExpressTrackList(id)));
}
@PutMapping("/delivery")
@Operation(summary = "订单发货")
@PreAuthorize("@ss.hasPermission('trade:order:update')")
public CommonResult<Boolean> deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) {
tradeOrderUpdateService.deliveryOrder(deliveryReqVO);
return success(true);
}
@PutMapping("/update-remark")
@Operation(summary = "订单备注")
@PreAuthorize("@ss.hasPermission('trade:order:update')")
public CommonResult<Boolean> updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) {
tradeOrderUpdateService.updateOrderRemark(reqVO);
return success(true);
}
@PutMapping("/update-price")
@Operation(summary = "订单调价")
@PreAuthorize("@ss.hasPermission('trade:order:update')")
public CommonResult<Boolean> updateOrderPrice(@RequestBody TradeOrderUpdatePriceReqVO reqVO) {
tradeOrderUpdateService.updateOrderPrice(reqVO);
return success(true);
}
@PutMapping("/update-address")
@Operation(summary = "修改订单收货地址")
@PreAuthorize("@ss.hasPermission('trade:order:update')")
public CommonResult<Boolean> updateOrderAddress(@RequestBody TradeOrderUpdateAddressReqVO reqVO) {
tradeOrderUpdateService.updateOrderAddress(reqVO);
return success(true);
}
@PutMapping("/pick-up-by-id")
@Operation(summary = "订单核销")
@Parameter(name = "id", description = "交易订单编号")
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
public CommonResult<Boolean> pickUpOrderById(@RequestParam("id") Long id) {
tradeOrderUpdateService.pickUpOrderByAdmin(id);
return success(true);
}
@PutMapping("/pick-up-by-verify-code")
@Operation(summary = "订单核销")
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
@PreAuthorize("@ss.hasPermission('trade:order:pick-up')")
public CommonResult<Boolean> pickUpOrderByVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
tradeOrderUpdateService.pickUpOrderByAdmin(pickUpVerifyCode);
return success(true);
}
@GetMapping("/get-by-pick-up-verify-code")
@Operation(summary = "查询核销码对应的订单")
@Parameter(name = "pickUpVerifyCode", description = "自提核销码")
@PreAuthorize("@ss.hasPermission('trade:order:query')")
public CommonResult<TradeOrderDetailRespVO> getByPickUpVerifyCode(@RequestParam("pickUpVerifyCode") String pickUpVerifyCode) {
TradeOrderDO tradeOrder = tradeOrderUpdateService.getByPickUpVerifyCode(pickUpVerifyCode);
return success(TradeOrderConvert.INSTANCE.convert2(tradeOrder, null));
}
}

View File

@ -0,0 +1,151 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 交易订单 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class TradeOrderBaseVO {
// ========== 订单基本信息 ==========
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "订单来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer terminal;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long userId;
@Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1")
private String userIp;
@Schema(description = "用户备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
private String userRemark;
@Schema(description = "订单状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "购买的商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer productCount;
@Schema(description = "订单完成时间")
private LocalDateTime finishTime;
@Schema(description = "订单取消时间")
private LocalDateTime cancelTime;
@Schema(description = "取消类型", example = "10")
private Integer cancelType;
@Schema(description = "商家备注", example = "你猜一下")
private String remark;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "支付订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long payOrderId;
@Schema(description = "是否已支付", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean payStatus;
@Schema(description = "付款时间")
private LocalDateTime payTime;
@Schema(description = "支付渠道", requiredMode = Schema.RequiredMode.REQUIRED, example = "wx_lite")
private String payChannelCode;
@Schema(description = "商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer totalPrice;
@Schema(description = "订单优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "运费金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer deliveryPrice;
@Schema(description = "订单调价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer adjustPrice;
@Schema(description = "应付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer payPrice;
// ========== 收件 + 物流基本信息 ==========
@Schema(description = "配送方式", example = "10")
private Integer deliveryType;
@Schema(description = "自提门店", example = "10")
private Long pickUpStoreId;
@Schema(description = "自提核销码", example = "10")
private Long pickUpVerifyCode;
@Schema(description = "配送模板编号", example = "1024")
private Long deliveryTemplateId;
@Schema(description = "发货物流公司编号", example = "1024")
private Long logisticsId;
@Schema(description = "发货物流单号", example = "1024")
private String logisticsNo;
@Schema(description = "发货时间")
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
private LocalDateTime receiveTime;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
private String receiverName;
@Schema(description = "收件人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000")
private String receiverMobile;
@Schema(description = "收件人地区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "110000")
private Integer receiverAreaId;
@Schema(description = "收件人详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "中关村大街 1 号")
private String receiverDetailAddress;
// ========== 售后基本信息 ==========
@Schema(description = "售后状态", example = "1")
private Integer afterSaleStatus;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer refundPrice;
// ========== 营销基本信息 ==========
@Schema(description = "优惠劵编号", example = "1024")
private Long couponId;
@Schema(description = "优惠劵减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer couponPrice;
@Schema(description = "积分抵扣的金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer pointPrice;
@Schema(description = "VIP 减免金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
private Integer vipPrice;
@Schema(description = "推广人编号", example = "1")
private Long brokerageUserId;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 订单发货 Request VO")
@Data
public class TradeOrderDeliveryReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "发货物流公司编号", example = "1")
@NotNull(message = "发货物流公司不能为空")
private Long logisticsId;
@Schema(description = "发货物流单号", example = "SF123456789")
private String logisticsNo;
}

View File

@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 交易订单的详情 Response VO")
@Data
public class TradeOrderDetailRespVO extends TradeOrderBaseVO {
/**
* 订单项列表
*/
private List<Item> items;
/**
* 下单用户信息
*/
private MemberUserRespVO user;
/**
* 推广用户信息
*/
private MemberUserRespVO brokerageUser;
/**
* 操作日志列表
*/
private List<OrderLog> logs;
@Schema(description = "收件人地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海 上海市 普陀区")
private String receiverAreaName;
@Schema(description = "管理后台 - 交易订单的操作日志")
@Data
public static class OrderLog {
@Schema(description = "操作详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单发货")
private String content;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-06-01 10:50:20")
private LocalDateTime createTime;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer userType;
}
@Schema(description = "管理后台 - 交易订单的详情的订单项目")
@Data
public static class Item extends TradeOrderItemBaseVO {
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
}
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 交易订单项 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class TradeOrderItemBaseVO {
// ========== 订单项基本信息 ==========
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long userId;
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderId;
// ========== 商品基本信息 ==========
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String picUrl;
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
// ========== 价格 + 支付基本信息 ==========
@Schema(description = "商品原价(单)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "商品优惠(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer discountPrice;
@Schema(description = "商品实付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer payPrice;
@Schema(description = "子订单分摊金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer orderPartPrice;
@Schema(description = "分摊后子订单实付金额(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer orderDividePrice;
// ========== 营销基本信息 ==========
// TODO 芋艿在捉摸一下
// ========== 售后基本信息 ==========
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer afterSaleStatus;
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 交易订单的分页项 Response VO")
@Data
public class TradeOrderPageItemRespVO extends TradeOrderBaseVO {
@Schema(description = "收件人地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海 上海市 普陀区")
private String receiverAreaName;
@Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Item> items;
@Schema(description = "用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
private MemberUserRespVO user;
@Schema(description = "推广人信息")
private MemberUserRespVO brokerageUser;
@Schema(description = "管理后台 - 交易订单的分页项的订单项目")
@Data
public static class Item extends TradeOrderItemBaseVO {
@Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<ProductPropertyValueDetailRespVO> properties;
}
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 交易订单的分页 Request VO")
@Data
public class TradeOrderPageReqVO extends PageParam {
@Schema(description = "订单号", example = "88888888")
private String no;
@Schema(description = "用户编号", example = "1024")
private Long userId;
@Schema(description = "用户昵称", example = "小王")
private String userNickname;
@Schema(description = "用户手机号", example = "小王")
@Mobile
private String userMobile;
@Schema(description = "配送方式", example = "1")
private Integer deliveryType;
@Schema(description = "发货物流公司编号", example = "1")
private Long logisticsId;
@Schema(description = "自提门店编号", example = "[1,2]")
private List<Long> pickUpStoreIds;
@Schema(description = "自提核销码", example = "12345678")
private String pickUpVerifyCode;
@Schema(description = "订单类型", example = "1")
private Integer type;
@Schema(description = "订单状态", example = "1")
@InEnum(value = TradeOrderStatusEnum.class, message = "订单状态必须是 {value}")
private Integer status;
@Schema(description = "支付渠道", example = "wx_lite")
private String payChannelCode;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "订单来源", example = "10")
@InEnum(value = TerminalEnum.class, message = "订单来源 {value}")
private Integer terminal;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 订单备注 Request VO")
@Data
public class TradeOrderRemarkReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "商家备注", example = "你猜一下")
@NotEmpty(message = "订单备注不能为空")
private String remark;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 交易订单统计 Response VO")
@Data
public class TradeOrderSummaryRespVO {
@Schema(description = "订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderCount;
@Schema(description = "订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderPayPrice;
@Schema(description = "退款单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long afterSaleCount;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long afterSalePrice;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 订单修改地址 Request VO")
@Data
public class TradeOrderUpdateAddressReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "收件人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "z张三")
@NotEmpty(message = "收件人名称不能为空")
private String receiverName;
@Schema(description = "收件人手机", requiredMode = Schema.RequiredMode.REQUIRED, example = "19988188888")
@NotEmpty(message = "收件人手机不能为空")
private String receiverMobile;
@Schema(description = "收件人地区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7310")
@NotNull(message = "收件人地区编号不能为空")
private Integer receiverAreaId;
@Schema(description = "收件人详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "昆明市五华区xxx小区xxx")
@NotEmpty(message = "收件人详细地址不能为空")
private String receiverDetailAddress;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.trade.controller.admin.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 订单改价 Request VO")
@Data
public class TradeOrderUpdatePriceReqVO {
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单编号不能为空")
private Long id;
@Schema(description = "订单调价,单位:分。正数,加价;负数,减价", requiredMode = Schema.RequiredMode.REQUIRED, example = "-100")
@NotNull(message = "订单调价价格不能为空")
private Integer adjustPrice;
}

View File

@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.trade.controller.app.aftersale;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO;
import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert;
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "用户 App - 交易售后")
@RestController
@RequestMapping("/trade/after-sale")
@Validated
@Slf4j
public class AppAfterSaleController {
@Resource
private AfterSaleService afterSaleService;
@GetMapping(value = "/page")
@Operation(summary = "获得售后分页")
public CommonResult<PageResult<AppAfterSaleRespVO>> getAfterSalePage(PageParam pageParam) {
return success(AfterSaleConvert.INSTANCE.convertPage02(
afterSaleService.getAfterSalePage(getLoginUserId(), pageParam)));
}
@GetMapping(value = "/get")
@Operation(summary = "获得售后订单")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
public CommonResult<AppAfterSaleRespVO> getAfterSale(@RequestParam("id") Long id) {
return success(AfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id)));
}
@GetMapping(value = "/get-applying-count")
@Operation(summary = "获得进行中的售后订单数量")
public CommonResult<Long> getApplyingAfterSaleCount() {
return success(afterSaleService.getApplyingAfterSaleCount(getLoginUserId()));
}
@PostMapping(value = "/create")
@Operation(summary = "申请售后")
public CommonResult<Long> createAfterSale(@RequestBody AppAfterSaleCreateReqVO createReqVO) {
return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
}
@PutMapping(value = "/delivery")
@Operation(summary = "退回货物")
public CommonResult<Boolean> deliveryAfterSale(@RequestBody AppAfterSaleDeliveryReqVO deliveryReqVO) {
afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO);
return success(true);
}
@DeleteMapping(value = "/cancel")
@Operation(summary = "取消售后")
@Parameter(name = "id", description = "售后编号", required = true, example = "1")
public CommonResult<Boolean> cancelAfterSale(@RequestParam("id") Long id) {
afterSaleService.cancelAfterSale(getLoginUserId(), id);
return success(true);
}
}

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "用户 App - 交易售后创建 Request VO")
@Data
public class AppAfterSaleCreateReqVO {
@Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "订单项编号不能为空")
private Long orderItemId;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "售后方式不能为空")
@InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
private Integer way;
@Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "退款金额不能为空")
@Min(value = 1, message = "退款金额必须大于 0")
private Integer refundPrice;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "申请原因不能为空")
private String applyReason;
@Schema(description = "补充描述", example = "商品质量不好")
private String applyDescription;
@Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png")
private List<String> applyPicUrls;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 交易售后退回货物 Request VO")
@Data
public class AppAfterSaleDeliveryReqVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "退货物流公司编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "退货物流公司编号不能为空")
private Long logisticsId;
@Schema(description = "退货物流单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SF123456789")
@NotNull(message = "退货物流单号不能为空")
private String logisticsNo;
}

View File

@ -0,0 +1,103 @@
package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 交易售后 Response VO")
@Data
public class AppAfterSaleRespVO {
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195")
private String no;
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer way;
@Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String applyReason;
@Schema(description = "补充描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String applyDescription;
@Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List<String> applyPicUrls;
// ========== 交易订单相关 ==========
@Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderId;
@Schema(description = "交易订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String orderNo;
@Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/01.jpg")
private String picUrl;
@Schema(description = "退货商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count;
// ========== 审批相关 ==========
/**
* 审批备注
*
* 注意只有审批不通过才会填写
*/
private String auditReason;
// ========== 退款相关 ==========
@Schema(description = "退款金额,单位:分", example = "100")
private Integer refundPrice;
@Schema(description = "退款时间")
private LocalDateTime refundTime;
// ========== 退货相关 ==========
@Schema(description = "退货物流公司编号", example = "1")
private Long logisticsId;
@Schema(description = "退货物流单号", example = "SF123456789")
private String logisticsNo;
@Schema(description = "退货时间")
private LocalDateTime deliveryTime;
@Schema(description = "收货时间")
private LocalDateTime receiveTime;
@Schema(description = "收货备注")
private String receiveReason;
}

View File

@ -0,0 +1,4 @@
/**
* 基础包放一些通用的 VO
*/
package cn.iocoder.yudao.module.trade.controller.app.base;

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.app.base.property;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 商品属性值的明细 Response VO")
@Data
public class AppProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.trade.controller.app.base.sku;
import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 商品 SKU 基础 Response VO
*
* @author 芋道源码
*/
@Data
public class AppProductSkuBaseRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "图片地址", example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer price;
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer stock;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.trade.controller.app.base.spu;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 商品 SPU 基础 Response VO
*
* @author 芋道源码
*/
@Data
public class AppProductSpuBaseRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "商品主图地址", example = "https://www.iocoder.cn/xx.png")
private String picUrl;
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
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.record.AppBrokerageProductPriceRespVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
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 javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
@Tag(name = "用户 APP - 分销用户")
@RestController
@RequestMapping("/trade/brokerage-record")
@Validated
@Slf4j
public class AppBrokerageRecordController {
@Resource
private BrokerageRecordService brokerageRecordService;
@GetMapping("/page")
@Operation(summary = "获得分销记录分页")
@PreAuthenticated
public CommonResult<PageResult<AppBrokerageRecordRespVO>> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) {
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(
BrokerageRecordConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
return success(BrokerageRecordConvert.INSTANCE.convertPage02(pageResult));
}
@GetMapping("/get-product-brokerage-price")
@Operation(summary = "获得商品的分销金额")
public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
return success(brokerageRecordService.calculateProductBrokeragePrice(getLoginUserId(), spuId));
}
}

View File

@ -0,0 +1,141 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
import cn.hutool.core.date.LocalDateTimeUtil;
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.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageUserConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.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.enums.brokerage.BrokerageWithdrawStatusEnum;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
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.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
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;
@Tag(name = "用户 APP - 分销用户")
@RestController
@RequestMapping("/trade/brokerage-user")
@Validated
@Slf4j
public class AppBrokerageUserController {
@Resource
private BrokerageUserService brokerageUserService;
@Resource
private BrokerageRecordService brokerageRecordService;
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/get")
@Operation(summary = "获得个人分销信息")
@PreAuthenticated
public CommonResult<AppBrokerageUserRespVO> getBrokerageUser() {
Optional<BrokerageUserDO> user = Optional.ofNullable(brokerageUserService.getBrokerageUser(getLoginUserId()));
// 返回数据
AppBrokerageUserRespVO respVO = new AppBrokerageUserRespVO()
.setBrokerageEnabled(user.map(BrokerageUserDO::getBrokerageEnabled).orElse(false))
.setBrokeragePrice(user.map(BrokerageUserDO::getBrokeragePrice).orElse(0))
.setFrozenPrice(user.map(BrokerageUserDO::getFrozenPrice).orElse(0));
return success(respVO);
}
@PutMapping("/bind")
@Operation(summary = "绑定推广员")
@PreAuthenticated
public CommonResult<Boolean> bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) {
return success(brokerageUserService.bindBrokerageUser(getLoginUserId(), reqVO.getBindUserId()));
}
@GetMapping("/get-summary")
@Operation(summary = "获得个人分销统计")
@PreAuthenticated
public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() {
// 查询当前登录用户信息
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(getLoginUserId());
// 统计用户昨日的佣金
LocalDateTime yesterday = LocalDateTime.now().minusDays(1);
LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday);
LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday);
Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(brokerageUser.getId(),
BrokerageRecordBizTypeEnum.ORDER, BrokerageRecordStatusEnum.SETTLEMENT, beginTime, endTime);
// 统计用户提现的佣金
Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(brokerageUser.getId()),
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream()
.findFirst().map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0);
// 统计分销用户数量一级
Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 1);
// 统计分销用户数量二级
Long secondBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 2);
// 拼接返回
return success(BrokerageUserConvert.INSTANCE.convert(yesterdayPrice, withdrawPrice, firstBrokerageUserCount, secondBrokerageUserCount, brokerageUser));
}
@GetMapping("/rank-page-by-user-count")
@Operation(summary = "获得分销用户排行分页(基于用户量)")
@PreAuthenticated
public CommonResult<PageResult<AppBrokerageUserRankByUserCountRespVO>> getBrokerageUserRankPageByUserCount(AppBrokerageUserRankPageReqVO pageReqVO) {
// 分页查询
PageResult<AppBrokerageUserRankByUserCountRespVO> pageResult = brokerageUserService.getBrokerageUserRankPageByUserCount(pageReqVO);
// 拼接数据
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByUserCountRespVO::getId));
return success(BrokerageUserConvert.INSTANCE.convertPage03(pageResult, userMap));
}
@GetMapping("/rank-page-by-price")
@Operation(summary = "获得分销用户排行分页(基于佣金)")
@PreAuthenticated
public CommonResult<PageResult<AppBrokerageUserRankByPriceRespVO>> getBrokerageUserChildSummaryPageByPrice(AppBrokerageUserRankPageReqVO pageReqVO) {
// 分页查询
PageResult<AppBrokerageUserRankByPriceRespVO> pageResult = brokerageRecordService.getBrokerageUserChildSummaryPageByPrice(pageReqVO);
// 拼接数据
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), AppBrokerageUserRankByPriceRespVO::getId));
return success(BrokerageRecordConvert.INSTANCE.convertPage03(pageResult, userMap));
}
@GetMapping("/child-summary-page")
@Operation(summary = "获得下级分销统计分页")
@PreAuthenticated
public CommonResult<PageResult<AppBrokerageUserChildSummaryRespVO>> getBrokerageUserChildSummaryPage(
AppBrokerageUserChildSummaryPageReqVO pageReqVO) {
PageResult<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserService.getBrokerageUserChildSummaryPage(pageReqVO, getLoginUserId());
return success(pageResult);
}
@GetMapping("/get-rank-by-price")
@Operation(summary = "获得分销用户排行(基于佣金)")
@Parameter(name = "times", description = "时间段", required = true)
public CommonResult<Integer> getRankByPrice(
@RequestParam("times") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime[] times) {
return success(brokerageRecordService.getUserRankByPrice(getLoginUserId(), times));
}
}

View File

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
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.withdraw.AppBrokerageWithdrawCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
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;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
@Tag(name = "用户 APP - 分销提现")
@RestController
@RequestMapping("/trade/brokerage-withdraw")
@Validated
@Slf4j
public class AppBrokerageWithdrawController {
@Resource
private BrokerageWithdrawService brokerageWithdrawService;
@GetMapping("/page")
@Operation(summary = "获得分销提现分页")
@PreAuthenticated
public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
}
@PostMapping("/create")
@Operation(summary = "创建分销提现")
@PreAuthenticated
public CommonResult<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) {
return success(brokerageWithdrawService.createBrokerageWithdraw(getLoginUserId(), createReqVO));
}
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 商品的分销金额 Response VO")
@Data
public class AppBrokerageProductPriceRespVO {
@Schema(description = "是否开启", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Boolean enabled;
@Schema(description = "分销最小金额,单位:分", example = "100")
private Integer brokerageMinPrice;
@Schema(description = "分销最大金额,单位:分", example = "100")
private Integer brokerageMaxPrice;
}

View File

@ -0,0 +1,22 @@
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;
@Schema(description = "应用 App - 分销记录分页 Request VO")
@Data
public class AppBrokerageRecordPageReqVO extends PageParam {
@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;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "用户 App - 分销记录 Response VO")
@Data
public class AppBrokerageRecordRespVO {
@Schema(description = "记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "分销标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "用户下单")
private String title;
@Schema(description = "分销金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Integer price;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "完成时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime finishTime;
}

View File

@ -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;
}

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.SortingField;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 下级分销统计分页 Request VO")
@Data
public class AppBrokerageUserChildSummaryPageReqVO extends PageParam {
public static final String SORT_FIELD_USER_COUNT = "userCount";
public static final String SORT_FIELD_ORDER_COUNT = "orderCount";
public static final String SORT_FIELD_PRICE = "price";
@Schema(description = "用户昵称", example = "") // 模糊匹配
private String nickname;
@Schema(description = "排序字段", example = "userCount")
private SortingField sortingField;
@Schema(description = "下级的级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 1 - 直接下级2 - 间接下级
@NotNull(message = "下级的级别不能为空")
@Range(min = 1, max = 2, message = "下级的级别只能是 {min} 或者 {max}")
private Integer level;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "用户 App - 下级分销统计 Response VO")
@Data
public class AppBrokerageUserChildSummaryRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
private String avatar;
@Schema(description = "佣金金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokeragePrice;
@Schema(description = "分销订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer brokerageOrderCount;
@Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
private Integer brokerageUserCount;
@Schema(description = "绑定推广员的时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime brokerageTime;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 个人分销统计 Response VO")
@Data
public class AppBrokerageUserMySummaryRespVO {
@Schema(description = "昨天的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer yesterdayPrice;
@Schema(description = "提现的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer withdrawPrice;
@Schema(description = "可用的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2408")
private Integer brokeragePrice;
@Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
private Integer frozenPrice;
@Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long firstBrokerageUserCount;
@Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long secondBrokerageUserCount;
}

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 分销排行用户(基于用户量) Response VO")
@Data
public class AppBrokerageUserRankByPriceRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
private String avatar;
@Schema(description = "佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer brokeragePrice;
}

Some files were not shown because too many files have changed in this diff Show More