mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-06-20 23:42:00 +08:00
!342 同步最新版本的商城进度
Merge pull request !342 from 芋道源码/feature/1.8.0-uniapp
This commit is contained in:
commit
30a4d7d954
@ -5,7 +5,7 @@
|
|||||||
"adminTenentId": "1",
|
"adminTenentId": "1",
|
||||||
|
|
||||||
"appApi": "http://127.0.0.1:48080/app-api",
|
"appApi": "http://127.0.0.1:48080/app-api",
|
||||||
"appToken": "test1",
|
"appToken": "test247",
|
||||||
"appTenentId": "1"
|
"appTenentId": "1"
|
||||||
},
|
},
|
||||||
"gateway": {
|
"gateway": {
|
||||||
|
@ -130,6 +130,11 @@
|
|||||||
<artifactId>yudao-spring-boot-starter-biz-error-code</artifactId>
|
<artifactId>yudao-spring-boot-starter-biz-error-code</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
<artifactId>yudao-spring-boot-starter-captcha</artifactId>
|
<artifactId>yudao-spring-boot-starter-captcha</artifactId>
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
<module>yudao-spring-boot-starter-biz-tenant</module>
|
<module>yudao-spring-boot-starter-biz-tenant</module>
|
||||||
<module>yudao-spring-boot-starter-biz-data-permission</module>
|
<module>yudao-spring-boot-starter-biz-data-permission</module>
|
||||||
<module>yudao-spring-boot-starter-biz-error-code</module>
|
<module>yudao-spring-boot-starter-biz-error-code</module>
|
||||||
|
<module>yudao-spring-boot-starter-biz-ip</module>
|
||||||
|
|
||||||
<module>yudao-spring-boot-starter-flowable</module>
|
<module>yudao-spring-boot-starter-flowable</module>
|
||||||
<module>yudao-spring-boot-starter-captcha</module>
|
<module>yudao-spring-boot-starter-captcha</module>
|
||||||
|
@ -20,7 +20,6 @@ public enum CommonStatusEnum implements IntArrayValuable {
|
|||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态值
|
* 状态值
|
||||||
*/
|
*/
|
||||||
|
@ -15,11 +15,12 @@ import java.util.Arrays;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum TerminalEnum implements IntArrayValuable {
|
public enum TerminalEnum implements IntArrayValuable {
|
||||||
|
|
||||||
//TODO terminal 重复,请参考 '订单来源终端:[1:小程序 2:H5 3:iOS 4:安卓]'
|
WECHAT_MINI_PROGRAM(10, "微信小程序"),
|
||||||
MINI_PROGRAM(1, "小程序"),
|
WECHAT_WAP(11, "微信公众号"),
|
||||||
H5(2, "H5"),
|
H5(20, "H5 网页"),
|
||||||
IOS(3, "iOS"),
|
IOS(31, "苹果 App"),
|
||||||
ANDROID(3, "安卓"),;
|
ANDROID(32, "安卓 App"),
|
||||||
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ public class DateUtils {
|
|||||||
|
|
||||||
public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
|
public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 LocalDateTime 转换成 Date
|
* 将 LocalDateTime 转换成 Date
|
||||||
*
|
*
|
||||||
|
59
yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml
Normal file
59
yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?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>
|
||||||
|
<artifactId>yudao-framework</artifactId>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<description>IP 拓展,支持如下功能:
|
||||||
|
1. IP 功能:查询 IP 对应的城市信息
|
||||||
|
基于 https://gitee.com/lionsoul/ip2region 实现
|
||||||
|
2. 城市功能:查询城市编码对应的城市信息
|
||||||
|
基于 https://github.com/modood/Administrative-divisions-of-China 实现
|
||||||
|
</description>
|
||||||
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<ip2region.version>2.6.6</ip2region.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- IP地址检索 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.lionsoul</groupId>
|
||||||
|
<artifactId>ip2region</artifactId>
|
||||||
|
<version>${ip2region.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,55 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 区域节点,包括国家、省份、城市、地区等信息
|
||||||
|
*
|
||||||
|
* 数据可见 resources/area.csv 文件
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Area {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号 - 全球,即根目录
|
||||||
|
*/
|
||||||
|
public static final Integer ID_GLOBAL = 0;
|
||||||
|
/**
|
||||||
|
* 编号 - 中国
|
||||||
|
*/
|
||||||
|
public static final Integer ID_CHINA = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*
|
||||||
|
* 枚举 {@link AreaTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父节点
|
||||||
|
*/
|
||||||
|
private Area parent;
|
||||||
|
/**
|
||||||
|
* 子节点
|
||||||
|
*/
|
||||||
|
private List<Area> children;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core.enums;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 区域类型枚举
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum AreaTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
COUNTRY(1, "国家"),
|
||||||
|
PROVINCE(2, "省份"),
|
||||||
|
CITY(3, "城市"),
|
||||||
|
DISTRICT(4, "地区"), // 县、镇、区等
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AreaTypeEnum::getType).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.text.csv.CsvRow;
|
||||||
|
import cn.hutool.core.text.csv.CsvUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 区域工具类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class AreaUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 SEARCHER
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
|
private final static AreaUtils INSTANCE = new AreaUtils();
|
||||||
|
|
||||||
|
|
||||||
|
private static Map<Integer, Area> areas;
|
||||||
|
|
||||||
|
private AreaUtils() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
areas = new HashMap<>();
|
||||||
|
areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
|
||||||
|
null, new ArrayList<>()));
|
||||||
|
// 从 csv 中加载数据
|
||||||
|
List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
|
||||||
|
rows.remove(0); // 删除 header
|
||||||
|
for (CsvRow row : rows) {
|
||||||
|
// 创建 Area 对象
|
||||||
|
Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
|
||||||
|
null, new ArrayList<>());
|
||||||
|
// 添加到 areas 中
|
||||||
|
areas.put(area.getId(), area);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
|
||||||
|
for (CsvRow row : rows) {
|
||||||
|
Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
|
||||||
|
Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
|
||||||
|
Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
|
||||||
|
area.setParent(parent);
|
||||||
|
parent.getChildren().add(area);
|
||||||
|
}
|
||||||
|
log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得指定编号对应的区域
|
||||||
|
*
|
||||||
|
* @param id 区域编号
|
||||||
|
* @return 区域
|
||||||
|
*/
|
||||||
|
public static Area getArea(Integer id) {
|
||||||
|
return areas.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化区域
|
||||||
|
*
|
||||||
|
* @param id 区域编号
|
||||||
|
* @return 格式化后的区域
|
||||||
|
*/
|
||||||
|
public static String format(Integer id) {
|
||||||
|
return format(id, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化区域
|
||||||
|
*
|
||||||
|
* 例如说:
|
||||||
|
* 1. id = “静安区”时:上海 上海市 静安区
|
||||||
|
* 2. id = “上海市”时:上海 上海市
|
||||||
|
* 3. id = “上海”时:上海
|
||||||
|
* 4. id = “美国”时:美国
|
||||||
|
* 当区域在中国时,默认不显示中国
|
||||||
|
*
|
||||||
|
* @param id 区域编号
|
||||||
|
* @param separator 分隔符
|
||||||
|
* @return 格式化后的区域
|
||||||
|
*/
|
||||||
|
public static String format(Integer id, String separator) {
|
||||||
|
// 获得区域
|
||||||
|
Area area = areas.get(id);
|
||||||
|
if (area == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < AreaTypeEnum.values().length; i++) { // 避免死循环
|
||||||
|
sb.insert(0, area.getName());
|
||||||
|
// “递归”父节点
|
||||||
|
area = area.getParent();
|
||||||
|
if (area == null
|
||||||
|
|| ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.insert(0, separator);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.lionsoul.ip2region.xdb.Searcher;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP 工具类
|
||||||
|
*
|
||||||
|
* IP 数据源来自 ip2region.xdb 精简版,基于 <a href="https://gitee.com/zhijiantianya/ip2region"/> 项目
|
||||||
|
*
|
||||||
|
* @author wanglhup
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class IPUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 SEARCHER
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
|
private final static IPUtils INSTANCE = new IPUtils();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP 查询器,启动加载到内存中
|
||||||
|
*/
|
||||||
|
private static Searcher SEARCHER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有化构造
|
||||||
|
*/
|
||||||
|
private IPUtils() {
|
||||||
|
try {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
|
||||||
|
SEARCHER = Searcher.newWithBuffer(bytes);
|
||||||
|
log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("启动加载 IPUtils 失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 IP 对应的地区编号
|
||||||
|
*
|
||||||
|
* @param ip IP 地址,格式为 127.0.0.1
|
||||||
|
* @return 地区id
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static Integer getAreaId(String ip) {
|
||||||
|
return Integer.parseInt(SEARCHER.search(ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 IP 对应的地区编号
|
||||||
|
*
|
||||||
|
* @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
|
||||||
|
* @return 地区编号
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static Integer getAreaId(long ip) {
|
||||||
|
return Integer.parseInt(SEARCHER.search(ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 IP 对应的地区
|
||||||
|
*
|
||||||
|
* @param ip IP 地址,格式为 127.0.0.1
|
||||||
|
* @return 地区
|
||||||
|
*/
|
||||||
|
public static Area getArea(String ip) {
|
||||||
|
return AreaUtils.getArea(getAreaId(ip));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 IP 对应的地区
|
||||||
|
*
|
||||||
|
* @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
|
||||||
|
* @return 地区
|
||||||
|
*/
|
||||||
|
public static Area getArea(long ip) {
|
||||||
|
return AreaUtils.getArea(getAreaId(ip));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* IP 拓展,支持如下功能:
|
||||||
|
*
|
||||||
|
* 1. IP 功能:查询 IP 对应的城市信息
|
||||||
|
* 基于 https://gitee.com/lionsoul/ip2region 实现
|
||||||
|
* 2. 城市功能:查询城市编码对应的城市信息
|
||||||
|
* 基于 https://github.com/modood/Administrative-divisions-of-China 实现
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.framework.ip;
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -0,0 +1,36 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link AreaUtils} 的单元测试
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class AreaUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetArea() {
|
||||||
|
// 调用:北京
|
||||||
|
Area area = AreaUtils.getArea(110100);
|
||||||
|
// 断言
|
||||||
|
assertEquals(area.getId(), 110100);
|
||||||
|
assertEquals(area.getName(), "北京市");
|
||||||
|
assertEquals(area.getType(), AreaTypeEnum.CITY.getType());
|
||||||
|
assertEquals(area.getParent().getId(), 110000);
|
||||||
|
assertEquals(area.getChildren().size(), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormat() {
|
||||||
|
assertEquals(AreaUtils.format(110105), "北京 北京市 朝阳区");
|
||||||
|
assertEquals(AreaUtils.format(1), "中国");
|
||||||
|
assertEquals(AreaUtils.format(2), "蒙古");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package cn.iocoder.yudao.framework.ip.core.utils;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.lionsoul.ip2region.xdb.Searcher;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link IPUtils} 的单元测试
|
||||||
|
*
|
||||||
|
* @author wanglhup
|
||||||
|
*/
|
||||||
|
public class IPUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAreaId_string() {
|
||||||
|
// 120.202.4.0|120.202.4.255|420600
|
||||||
|
Integer areaId = IPUtils.getAreaId("120.202.4.50");
|
||||||
|
assertEquals(420600, areaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAreaId_long() throws Exception {
|
||||||
|
// 120.203.123.0|120.203.133.255|360900
|
||||||
|
long ip = Searcher.checkIP("120.203.123.250");
|
||||||
|
Integer areaId = IPUtils.getAreaId(ip);
|
||||||
|
assertEquals(360900, areaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetArea_string() {
|
||||||
|
// 120.202.4.0|120.202.4.255|420600
|
||||||
|
Area area = IPUtils.getArea("120.202.4.50");
|
||||||
|
assertEquals("襄阳市", area.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetArea_long() throws Exception {
|
||||||
|
// 120.203.123.0|120.203.133.255|360900
|
||||||
|
long ip = Searcher.checkIP("120.203.123.252");
|
||||||
|
Area area = IPUtils.getArea(ip);
|
||||||
|
assertEquals("宜春市", area.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,26 +13,23 @@ import javax.validation.constraints.NotEmpty;
|
|||||||
public class PayProperties {
|
public class PayProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付回调地址
|
* 回调地址
|
||||||
|
*
|
||||||
|
* 实际上,对应的 PayNotifyController 的 notifyCallback 方法的 URL
|
||||||
|
*
|
||||||
* 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址
|
* 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "支付回调地址不能为空")
|
@NotEmpty(message = "回调地址不能为空")
|
||||||
@URL(message = "支付回调地址的格式必须是 URL")
|
@URL(message = "回调地址的格式必须是 URL")
|
||||||
private String payNotifyUrl;
|
private String callbackUrl;
|
||||||
/**
|
|
||||||
* 退款回调地址
|
|
||||||
* 注意点,同 {@link #payNotifyUrl} 属性
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "退款回调地址不能为空")
|
|
||||||
@URL(message = "退款回调地址的格式必须是 URL")
|
|
||||||
private String refundNotifyUrl;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付完成的返回地址
|
* 回跳地址
|
||||||
|
*
|
||||||
|
* 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL
|
||||||
*/
|
*/
|
||||||
@URL(message = "支付返回的地址的格式必须是 URL")
|
@URL(message = "回跳地址的格式必须是 URL")
|
||||||
@NotEmpty(message = "支付返回的地址不能为空")
|
@NotEmpty(message = "回跳地址不能为空")
|
||||||
private String payReturnUrl;
|
private String returnUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ public class PayNotifyDataDTO {
|
|||||||
*/
|
*/
|
||||||
private String body;
|
private String body;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
|
* HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
|
||||||
*/
|
*/
|
||||||
private Map<String,String> params;
|
private Map<String,String> params;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class PayOrderUnifiedReqDTO {
|
|||||||
*/
|
*/
|
||||||
@NotNull(message = "支付金额不能为空")
|
@NotNull(message = "支付金额不能为空")
|
||||||
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
||||||
private Long amount;
|
private Integer amount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付过期时间
|
* 支付过期时间
|
||||||
|
@ -63,7 +63,7 @@ public class PayRefundUnifiedReqDTO {
|
|||||||
*/
|
*/
|
||||||
@NotNull(message = "退款金额不能为空")
|
@NotNull(message = "退款金额不能为空")
|
||||||
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
|
||||||
private Long amount;
|
private Integer amount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
|
* 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要
|
||||||
|
@ -69,7 +69,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
|||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Double calculateAmount(Long amount) {
|
protected Double calculateAmount(Integer amount) {
|
||||||
return amount / 100.0;
|
return amount / 100.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.framework.core.client.impl;
|
package cn.iocoder.yudao.framework.pay.core.client.impl;
|
||||||
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
|
||||||
@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
|
|||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||||
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -24,7 +24,8 @@ import java.io.FileNotFoundException;
|
|||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public class PayClientFactoryImplTest {
|
@Disabled
|
||||||
|
public class PayClientFactoryImplIntegrationTest {
|
||||||
|
|
||||||
private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
|
private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ public class PayClientFactoryImplTest {
|
|||||||
PayClient client = payClientFactory.getPayClient(channelId);
|
PayClient client = payClientFactory.getPayClient(channelId);
|
||||||
// 发起支付
|
// 发起支付
|
||||||
PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO();
|
PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO();
|
||||||
reqDTO.setNotifyUrl("http://niubi.natapp1.cc/api/pay/order/notify/alipay-qr/1"); // TODO @tina: 这里改成你的 natapp 回调地址
|
reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址
|
||||||
CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO);
|
CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO);
|
||||||
System.out.println(JsonUtils.toJsonString(result));
|
System.out.println(JsonUtils.toJsonString(result));
|
||||||
System.out.println(result.getData().getQrCode());
|
System.out.println(result.getData().getQrCode());
|
||||||
@ -121,7 +122,7 @@ public class PayClientFactoryImplTest {
|
|||||||
|
|
||||||
private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
|
private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
|
||||||
PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
|
PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
|
||||||
reqDTO.setAmount(123L);
|
reqDTO.setAmount(123);
|
||||||
reqDTO.setSubject("IPhone 13");
|
reqDTO.setSubject("IPhone 13");
|
||||||
reqDTO.setBody("biubiubiu");
|
reqDTO.setBody("biubiubiu");
|
||||||
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
@ -73,7 +73,7 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
|
|||||||
Long shopOrderId = System.currentTimeMillis();
|
Long shopOrderId = System.currentTimeMillis();
|
||||||
PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();
|
PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO();
|
||||||
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
|
||||||
reqDTO.setAmount(1L);
|
reqDTO.setAmount(1);
|
||||||
reqDTO.setBody("内容:" + shopOrderId);
|
reqDTO.setBody("内容:" + shopOrderId);
|
||||||
reqDTO.setSubject("标题:"+shopOrderId);
|
reqDTO.setSubject("标题:"+shopOrderId);
|
||||||
String notify="http://niubi.natapp1.cc/api/pay/order/notify";
|
String notify="http://niubi.natapp1.cc/api/pay/order/notify";
|
||||||
|
@ -2,6 +2,10 @@ package cn.iocoder.yudao.framework.tenant.core.util;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多租户 Util
|
* 多租户 Util
|
||||||
*
|
*
|
||||||
@ -32,4 +36,16 @@ public class TenantUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将多租户编号,添加到 header 中
|
||||||
|
*
|
||||||
|
* @param headers HTTP 请求 headers
|
||||||
|
*/
|
||||||
|
public static void addTenantHeader(Map<String, String> headers) {
|
||||||
|
Long tenantId = TenantContextHolder.getTenantId();
|
||||||
|
if (tenantId != null) {
|
||||||
|
headers.put(HEADER_TENANT_ID, tenantId.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.mybatis.core.mapper;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@ -75,9 +76,13 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
|
|||||||
return selectList(new LambdaQueryWrapper<T>().in(field, values));
|
return selectList(new LambdaQueryWrapper<T>().in(field, values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
|
||||||
|
return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 逐条插入,适合少量数据插入,或者对性能要求不高的场景
|
* 逐条插入,适合少量数据插入,或者对性能要求不高的场景
|
||||||
*
|
* <p>
|
||||||
* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
|
* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
|
||||||
* 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
|
* 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
|
||||||
*
|
*
|
||||||
|
@ -33,6 +33,10 @@ public class AssertUtils {
|
|||||||
public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
|
public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
|
||||||
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
|
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
|
||||||
Arrays.stream(expectedFields).forEach(expectedField -> {
|
Arrays.stream(expectedFields).forEach(expectedField -> {
|
||||||
|
// 忽略 jacoco 自动生成的 $jacocoData 属性的情况
|
||||||
|
if (expectedField.isSynthetic()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 如果是忽略的属性,则不进行比对
|
// 如果是忽略的属性,则不进行比对
|
||||||
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
|
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
|
||||||
return;
|
return;
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.framework.jackson.core.databind;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
public class LocalTimeJson {
|
||||||
|
|
||||||
|
public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
|
||||||
|
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
|
||||||
|
.withZone(ZoneId.systemDefault()));
|
||||||
|
|
||||||
|
public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
|
||||||
|
.ofPattern(FORMAT_HOUR_MINUTE_SECOND)
|
||||||
|
.withZone(ZoneId.systemDefault()));
|
||||||
|
|
||||||
|
}
|
@ -18,6 +18,8 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.hutool.core.text.CharSequenceUtil.*;
|
import static cn.hutool.core.text.CharSequenceUtil.*;
|
||||||
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
|
import static cn.hutool.core.util.RandomUtil.randomInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代码生成器的 Builder,负责:
|
* 代码生成器的 Builder,负责:
|
||||||
@ -128,6 +130,7 @@ public class CodegenBuilder {
|
|||||||
// 初始化 Column 列的默认字段
|
// 初始化 Column 列的默认字段
|
||||||
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
|
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
|
||||||
processColumnUI(column); // 处理 UI 相关的字段的默认值
|
processColumnUI(column); // 处理 UI 相关的字段的默认值
|
||||||
|
processColumnExample(column); // 处理字段的 swagger example 示例
|
||||||
}
|
}
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
@ -169,4 +172,42 @@ public class CodegenBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理字段的 swagger example 示例
|
||||||
|
*
|
||||||
|
* @param column 字段
|
||||||
|
*/
|
||||||
|
private void processColumnExample(CodegenColumnDO column) {
|
||||||
|
// id、price、count 等可能是整数的后缀
|
||||||
|
if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) {
|
||||||
|
column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// name
|
||||||
|
if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) {
|
||||||
|
column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// status
|
||||||
|
if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) {
|
||||||
|
column.setExample(randomEle(new String[]{"1", "2"}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// url
|
||||||
|
if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) {
|
||||||
|
column.setExample("https://www.iocoder.cn");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// reason
|
||||||
|
if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) {
|
||||||
|
column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// description、memo、remark
|
||||||
|
if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) {
|
||||||
|
column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.api.property;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品属性值 API 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface ProductPropertyValueApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编号数组,获得属性值列表
|
||||||
|
*
|
||||||
|
* @param ids 编号数组
|
||||||
|
* @return 属性值明细列表
|
||||||
|
*/
|
||||||
|
List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.api.property.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品属性项的明细 Response DTO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProductPropertyValueDetailRespDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性的编号
|
||||||
|
*/
|
||||||
|
private Long propertyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性的名称
|
||||||
|
*/
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性值的编号
|
||||||
|
*/
|
||||||
|
private Long valueId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性值的名称
|
||||||
|
*/
|
||||||
|
private String valueName;
|
||||||
|
|
||||||
|
}
|
@ -18,17 +18,17 @@ public class ProductSkuRespDTO {
|
|||||||
* 商品 SKU 编号,自增
|
* 商品 SKU 编号,自增
|
||||||
*/
|
*/
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
|
||||||
* 商品 SKU 名字
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
/**
|
/**
|
||||||
* SPU 编号
|
* SPU 编号
|
||||||
*/
|
*/
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
|
/**
|
||||||
|
* SPU 名字
|
||||||
|
*/
|
||||||
|
private String spuName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值数组,JSON 格式
|
* 属性数组,JSON 格式
|
||||||
*/
|
*/
|
||||||
private List<Property> properties;
|
private List<Property> properties;
|
||||||
/**
|
/**
|
||||||
|
@ -15,28 +15,30 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
|
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
|
||||||
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
|
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
|
||||||
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
|
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
|
||||||
ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
|
|
||||||
|
|
||||||
// ========== 商品品牌相关编号 1008002000 ==========
|
// ========== 商品品牌相关编号 1008002000 ==========
|
||||||
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
||||||
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
|
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
|
||||||
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
|
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
|
||||||
|
|
||||||
// ========== 商品规格名称 1008003000 ==========
|
// ========== 商品属性项 1008003000 ==========
|
||||||
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
|
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
|
||||||
ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在");
|
ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
|
||||||
|
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
|
||||||
|
|
||||||
// ========== 规格值 1008004000 ==========
|
// ========== 商品属性值 1008004000 ==========
|
||||||
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
|
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
|
||||||
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在");
|
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
|
||||||
|
|
||||||
// ========== 商品 SPU 1008005000 ==========
|
// ========== 商品 SPU 1008005000 ==========
|
||||||
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
|
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
|
||||||
|
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
|
||||||
|
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
|
||||||
|
|
||||||
// ========== 商品 SKU 1008006000 ==========
|
// ========== 商品 SKU 1008006000 ==========
|
||||||
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
|
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
|
||||||
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
|
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
|
||||||
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
|
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
|
||||||
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
|
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
|
||||||
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
|
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
|
||||||
|
|
||||||
|
@ -21,11 +21,11 @@ public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
|
|||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格
|
* 规格类型
|
||||||
*/
|
*/
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
/**
|
/**
|
||||||
* 规格名
|
* 规格名称
|
||||||
*/
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
|
|||||||
return ARRAYS;
|
return ARRAYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否处于【上架】状态
|
||||||
|
*
|
||||||
|
* @param status 状态
|
||||||
|
* @return 是否处于【上架】状态
|
||||||
|
*/
|
||||||
|
public static boolean isEnable(Integer status) {
|
||||||
|
return ENABLE.getStatus().equals(status);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.api.property;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||||
|
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 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids) {
|
||||||
|
return ProductPropertyValueConvert.INSTANCE.convertList02(
|
||||||
|
productPropertyValueService.getPropertyValueDetailList(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,14 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.property;
|
package cn.iocoder.yudao.module.product.controller.admin.property;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
@ -13,12 +18,13 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
|
||||||
@Api(tags = "管理后台 - 规格名称")
|
@Api(tags = "管理后台 - 商品属性项")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/product/property")
|
@RequestMapping("/product/property")
|
||||||
@Validated
|
@Validated
|
||||||
@ -26,16 +32,18 @@ public class ProductPropertyController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductPropertyService productPropertyService;
|
private ProductPropertyService productPropertyService;
|
||||||
|
@Resource
|
||||||
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@ApiOperation("创建规格名称")
|
@ApiOperation("创建属性项")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:create')")
|
@PreAuthorize("@ss.hasPermission('product:property:create')")
|
||||||
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
|
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
|
||||||
return success(productPropertyService.createProperty(createReqVO));
|
return success(productPropertyService.createProperty(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@ApiOperation("更新规格名称")
|
@ApiOperation("更新属性项")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:update')")
|
@PreAuthorize("@ss.hasPermission('product:property:update')")
|
||||||
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
|
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
|
||||||
productPropertyService.updateProperty(updateReqVO);
|
productPropertyService.updateProperty(updateReqVO);
|
||||||
@ -43,7 +51,7 @@ public class ProductPropertyController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@ApiOperation("删除规格名称")
|
@ApiOperation("删除属性项")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:delete')")
|
@PreAuthorize("@ss.hasPermission('product:property:delete')")
|
||||||
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
|
||||||
@ -52,32 +60,40 @@ public class ProductPropertyController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@ApiOperation("获得规格名称")
|
@ApiOperation("获得属性项")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
|
public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
|
||||||
return success(productPropertyService.getProperty(id));
|
return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperation("获得规格名称列表")
|
@ApiOperation("获得属性项列表")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
|
public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
|
||||||
return success(productPropertyService.getPropertyList(listReqVO));
|
return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@ApiOperation("获得规格名称分页")
|
@ApiOperation("获得属性项分页")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
|
public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
|
||||||
return success(productPropertyService.getPropertyPage(pageVO));
|
return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/listAndValue")
|
@GetMapping("/get-value-list")
|
||||||
@ApiOperation("获得规格名称列表")
|
@ApiOperation("获得属性项列表")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
|
public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
|
||||||
return success(productPropertyService.getPropertyAndValueList(listReqVO));
|
// 查询属性项
|
||||||
|
List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO);
|
||||||
|
if (CollUtil.isEmpty(keys)) {
|
||||||
|
return success(Collections.emptyList());
|
||||||
|
}
|
||||||
|
// 查询属性值
|
||||||
|
List<ProductPropertyValueDO> values = productPropertyValueService.getPropertyValueListByPropertyId(
|
||||||
|
convertSet(keys, ProductPropertyDO::getId));
|
||||||
|
return success(ProductPropertyConvert.INSTANCE.convertList(keys, values));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.property;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
|
||||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
@ -20,7 +20,7 @@ import javax.validation.Valid;
|
|||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
@Api(tags = "管理后台 - 规格值名称")
|
@Api(tags = "管理后台 - 商品属性值")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/product/property/value")
|
@RequestMapping("/product/property/value")
|
||||||
@Validated
|
@Validated
|
||||||
@ -30,14 +30,14 @@ public class ProductPropertyValueController {
|
|||||||
private ProductPropertyValueService productPropertyValueService;
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@ApiOperation("创建规格名称")
|
@ApiOperation("创建属性值")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:create')")
|
@PreAuthorize("@ss.hasPermission('product:property:create')")
|
||||||
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
|
public CommonResult<Long> createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
|
||||||
return success(productPropertyValueService.createPropertyValue(createReqVO));
|
return success(productPropertyValueService.createPropertyValue(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@ApiOperation("更新规格名称")
|
@ApiOperation("更新属性值")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:update')")
|
@PreAuthorize("@ss.hasPermission('product:property:update')")
|
||||||
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
|
public CommonResult<Boolean> updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
|
||||||
productPropertyValueService.updatePropertyValue(updateReqVO);
|
productPropertyValueService.updatePropertyValue(updateReqVO);
|
||||||
@ -45,7 +45,7 @@ public class ProductPropertyValueController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@ApiOperation("删除规格名称")
|
@ApiOperation("删除属性值")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:delete')")
|
@PreAuthorize("@ss.hasPermission('product:property:delete')")
|
||||||
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteProperty(@RequestParam("id") Long id) {
|
||||||
@ -54,17 +54,17 @@ public class ProductPropertyValueController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
@GetMapping("/get")
|
||||||
@ApiOperation("获得规格名称")
|
@ApiOperation("获得属性值")
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) {
|
public CommonResult<ProductPropertyValueRespVO> getProperty(@RequestParam("id") Long id) {
|
||||||
return success(productPropertyValueService.getPropertyValue(id));
|
return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@ApiOperation("获得规格名称分页")
|
@ApiOperation("获得属性值分页")
|
||||||
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
@PreAuthorize("@ss.hasPermission('product:property:query')")
|
||||||
public CommonResult<PageResult<ProductPropertyValueRespVO>> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
|
public CommonResult<PageResult<ProductPropertyValueRespVO>> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
|
||||||
return success(productPropertyValueService.getPropertyValueListPage(pageVO));
|
return success(ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueService.getPropertyValuePage(pageVO)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.property.vo;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description: ProductPropertyViewRespVO
|
|
||||||
* @Author: franky
|
|
||||||
* @CreateDate: 2022/7/5 21:29
|
|
||||||
* @Version: 1.0.0
|
|
||||||
*/
|
|
||||||
@ApiModel("管理后台 - 规格名称详情展示 Request VO")
|
|
||||||
@Data
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class ProductPropertyViewRespVO {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格名称id", example = "1")
|
|
||||||
public Long propertyId;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格名称", example = "内存")
|
|
||||||
public String name;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]")
|
|
||||||
public List<Tuple2> propertyValues;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@ApiModel(value = "规格属性值元组")
|
|
||||||
public static class Tuple2 {
|
|
||||||
private final long id;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public Tuple2(Long id, String name) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +1,36 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
|
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格 + 规格值 Response VO")
|
@ApiModel("管理后台 - 商品属性项 + 属性值 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
public class ProductPropertyAndValueRespVO {
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格的编号", required = true, example = "1024")
|
@ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间", required = true)
|
@ApiModelProperty(value = "属性项的名称", required = true, example = "颜色")
|
||||||
private LocalDateTime createTime;
|
private String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值的集合
|
* 属性值的集合
|
||||||
*/
|
*/
|
||||||
private List<ProductPropertyValueRespVO> values;
|
private List<Value> values;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 属性值的简单 Response VO")
|
||||||
|
@Data
|
||||||
|
public static class Value {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的编号", required = true, example = "2048")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,19 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
|
* 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ProductPropertyBaseVO {
|
public class ProductPropertyBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格名称", required = true, example = "颜色")
|
@ApiModelProperty(value = "名称", required = true, example = "颜色")
|
||||||
@NotBlank(message = "规格名称不能为空")
|
@NotBlank(message = "名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "备注", example = "颜色")
|
@ApiModelProperty(value = "备注", example = "颜色")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
|
||||||
@NotNull(message = "状态不能为空")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格名称创建 Request VO")
|
@ApiModel("管理后台 - 属性项创建 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@ -5,15 +5,12 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格名称 List Request VO")
|
@ApiModel("管理后台 - 属性项 List Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductPropertyListReqVO {
|
public class ProductPropertyListReqVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格名称", example = "颜色")
|
@ApiModelProperty(value = "名称", example = "颜色")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,13 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格名称分页 Request VO")
|
@ApiModel("管理后台 - 属性项 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductPropertyPageReqVO extends PageParam {
|
public class ProductPropertyPageReqVO extends PageParam {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格名称", example = "颜色")
|
@ApiModelProperty(value = "名称", example = "颜色")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
||||||
|
@ -8,13 +8,13 @@ import lombok.ToString;
|
|||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格 + 规格值 Response VO")
|
@ApiModel("管理后台 - 属性项 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
|
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格的编号", required = true, example = "1024")
|
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间", required = true)
|
@ApiModelProperty(value = "创建时间", required = true)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
|
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
import io.swagger.annotations.ApiModel;
|
||||||
import lombok.*;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import io.swagger.annotations.*;
|
import lombok.Data;
|
||||||
import javax.validation.constraints.*;
|
import lombok.EqualsAndHashCode;
|
||||||
import java.util.List;
|
import lombok.ToString;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格名称更新 Request VO")
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 属性项更新 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@ -7,24 +7,20 @@ import javax.validation.constraints.NotEmpty;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
|
* 属性值 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class ProductPropertyValueBaseVO {
|
public class ProductPropertyValueBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格编号", required = true, example = "1024")
|
@ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
|
||||||
@NotNull(message = "规格编号不能为空")
|
@NotNull(message = "属性项的编号不能为空")
|
||||||
private Long propertyId;
|
private Long propertyId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格值名字", required = true, example = "红色")
|
@ApiModelProperty(value = "名称", required = true, example = "红色")
|
||||||
@NotEmpty(message = "规格值名字不能为空")
|
@NotEmpty(message = "名称名字不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
|
||||||
@NotNull(message = "状态不能为空")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "备注", example = "颜色")
|
@ApiModelProperty(value = "备注", example = "颜色")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.*;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格值创建 Request VO")
|
@ApiModel("管理后台 - 商品属性值创建 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ApiModel("管理后台 - 商品属性值的明细 Response VO")
|
||||||
|
@Data
|
||||||
|
public class ProductPropertyValueDetailRespVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性的编号", required = true, example = "1")
|
||||||
|
private Long propertyId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
|
||||||
|
private Long valueId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
|
||||||
|
private String valueName;
|
||||||
|
|
||||||
|
}
|
@ -6,23 +6,17 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
@ApiModel("管理后台 - 商品属性值分页 Request VO")
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格名称值分页 Request VO")
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductPropertyValuePageReqVO extends PageParam {
|
public class ProductPropertyValuePageReqVO extends PageParam {
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格id", example = "1024")
|
@ApiModelProperty(value = "属性项的编号", example = "1024")
|
||||||
private String propertyId;
|
private String propertyId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格值", example = "红色")
|
@ApiModelProperty(value = "名称", example = "红色")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
|
||||||
|
@ -8,13 +8,13 @@ import lombok.ToString;
|
|||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格值 Response VO")
|
@ApiModel("管理后台 - 商品属性值 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
|
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "主键", required = true, example = "10")
|
@ApiModelProperty(value = "编号", required = true, example = "10")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间")
|
@ApiModelProperty(value = "创建时间")
|
||||||
|
@ -4,7 +4,7 @@ import lombok.*;
|
|||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.*;
|
||||||
import javax.validation.constraints.*;
|
import javax.validation.constraints.*;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 规格值更新 Request VO")
|
@ApiModel("管理后台 - 商品属性值更新 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
@ -55,8 +57,10 @@ public class ProductSkuBaseVO {
|
|||||||
@ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
|
@ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
|
||||||
private Double volume;
|
private Double volume;
|
||||||
|
|
||||||
@ApiModel("规格值")
|
@ApiModel("商品属性")
|
||||||
@Data
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
public static class Property {
|
public static class Property {
|
||||||
|
|
||||||
@ApiModelProperty(value = "属性编号", required = true, example = "1")
|
@ApiModelProperty(value = "属性编号", required = true, example = "1")
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
|
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@ -14,11 +13,8 @@ import java.util.List;
|
|||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
|
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "商品 SKU 编号", example = "1")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值数组
|
* 属性数组
|
||||||
*/
|
*/
|
||||||
private List<Property> properties;
|
private List<Property> properties;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
|
|||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值数组
|
* 属性数组
|
||||||
*/
|
*/
|
||||||
private List<Property> properties;
|
private List<Property> properties;
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
### 获得商品 SPU 明细
|
||||||
|
GET {{baseUrl}}/product/spu/get-detail?id=4
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
tenant-id: {{adminTenentId}}
|
@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
|
|||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
||||||
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||||
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
||||||
|
|
||||||
@Api(tags = "管理后台 - 商品 SPU")
|
@Api(tags = "管理后台 - 商品 SPU")
|
||||||
@RestController
|
@RestController
|
||||||
@ -27,20 +33,24 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
|||||||
public class ProductSpuController {
|
public class ProductSpuController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductSpuService spuService;
|
private ProductSpuService productSpuService;
|
||||||
|
@Resource
|
||||||
|
private ProductSkuService productSkuService;
|
||||||
|
@Resource
|
||||||
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@ApiOperation("创建商品 SPU")
|
@ApiOperation("创建商品 SPU")
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:create')")
|
@PreAuthorize("@ss.hasPermission('product:spu:create')")
|
||||||
public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
|
public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
|
||||||
return success(spuService.createSpu(createReqVO));
|
return success(productSpuService.createSpu(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@ApiOperation("更新商品 SPU")
|
@ApiOperation("更新商品 SPU")
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:update')")
|
@PreAuthorize("@ss.hasPermission('product:spu:update')")
|
||||||
public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
|
public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
|
||||||
spuService.updateSpu(updateReqVO);
|
productSpuService.updateSpu(updateReqVO);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,42 +59,35 @@ public class ProductSpuController {
|
|||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
|
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
|
||||||
public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteSpu(@RequestParam("id") Long id) {
|
||||||
spuService.deleteSpu(id);
|
productSpuService.deleteSpu(id);
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 芋艿:修改接口
|
@GetMapping("/get-detail")
|
||||||
@GetMapping("/get/detail")
|
@ApiOperation("获得商品 SPU 明细")
|
||||||
@ApiOperation("获得商品 SPU")
|
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
||||||
public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
|
public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
|
||||||
return success(spuService.getSpuDetail(id));
|
// 获得商品 SPU
|
||||||
|
ProductSpuDO spu = productSpuService.getSpu(id);
|
||||||
|
if (spu == null) {
|
||||||
|
throw exception(SPU_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get")
|
// 查询商品 SKU
|
||||||
@ApiOperation("获得商品 SPU")
|
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
|
||||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
// 查询商品属性
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
|
||||||
public CommonResult<ProductSpuRespVO> getSpu(@RequestParam("id") Long id) {
|
.getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
|
||||||
return success(spuService.getSpu(id));
|
// 拼接
|
||||||
}
|
return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/list")
|
|
||||||
@ApiOperation("获得商品 SPU 列表")
|
|
||||||
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
|
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
|
||||||
public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) {
|
|
||||||
List<ProductSpuDO> list = spuService.getSpuList(ids);
|
|
||||||
return success(ProductSpuConvert.INSTANCE.convertList(list));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-simple-list")
|
@GetMapping("/get-simple-list")
|
||||||
@ApiOperation("获得商品 SPU 精简列表")
|
@ApiOperation("获得商品 SPU 精简列表")
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
||||||
public CommonResult<List<ProductSpuSimpleRespVO>> getSpuSimpleList() {
|
public CommonResult<List<ProductSpuSimpleRespVO>> getSpuSimpleList() {
|
||||||
List<ProductSpuDO> list = spuService.getSpuList();
|
List<ProductSpuDO> list = productSpuService.getSpuList();
|
||||||
return success(ProductSpuConvert.INSTANCE.convertList02(list));
|
return success(ProductSpuConvert.INSTANCE.convertList02(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +95,7 @@ public class ProductSpuController {
|
|||||||
@ApiOperation("获得商品 SPU 分页")
|
@ApiOperation("获得商品 SPU 分页")
|
||||||
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
@PreAuthorize("@ss.hasPermission('product:spu:query')")
|
||||||
public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
|
public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
|
||||||
return success(spuService.getSpuPage(pageVO));
|
return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,28 +64,13 @@ public class ProductSpuBaseVO {
|
|||||||
@NotNull(message = "是否展示库存不能为空")
|
@NotNull(message = "是否展示库存不能为空")
|
||||||
private Boolean showStock;
|
private Boolean showStock;
|
||||||
|
|
||||||
@ApiModelProperty(value = "库存", required = true, example = "true")
|
|
||||||
private Integer totalStock;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "市场价", example = "1024")
|
@ApiModelProperty(value = "市场价", example = "1024")
|
||||||
private Integer marketPrice;
|
private Integer marketPrice;
|
||||||
|
|
||||||
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
|
|
||||||
private Integer minPrice;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
|
|
||||||
private Integer maxPrice;
|
|
||||||
|
|
||||||
// ========== 统计相关字段 =========
|
// ========== 统计相关字段 =========
|
||||||
|
|
||||||
@ApiModelProperty(value = "商品销量", example = "1024")
|
|
||||||
private Integer salesCount;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
|
@ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
|
||||||
@NotNull(message = "虚拟销量不能为空")
|
@NotNull(message = "虚拟销量不能为空")
|
||||||
private Integer virtualSalesCount;
|
private Integer virtualSalesCount;
|
||||||
|
|
||||||
@ApiModelProperty(value = "点击量", example = "1024")
|
|
||||||
private Integer clickCount;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,21 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
|
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
|
@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
|
public class ProductSpuDetailRespVO extends ProductSpuRespVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "主键", required = true, example = "1")
|
// ========== SKU 相关字段 =========
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "创建时间")
|
|
||||||
private LocalDateTime createTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SKU 数组
|
* SKU 数组
|
||||||
@ -35,31 +29,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
|
|||||||
public static class Sku extends ProductSkuBaseVO {
|
public static class Sku extends ProductSkuBaseVO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格的数组
|
* 属性数组
|
||||||
*/
|
*/
|
||||||
private List<ProductSpuDetailRespVO.Property> properties;
|
private List<ProductPropertyValueDetailRespVO> properties;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiModel(value = "管理后台 - 商品规格的详细 Response VO")
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public static class Property extends ProductSkuBaseVO.Property {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格的名字", required = true, example = "颜色")
|
|
||||||
private String propertyName;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "规格值的名字", required = true, example = "蓝色")
|
|
||||||
private String valueName;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4")
|
|
||||||
private Long categoryId;
|
|
||||||
|
|
||||||
// TODO @芋艿:在瞅瞅~
|
|
||||||
@ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
|
|
||||||
private List<ProductPropertyViewRespVO> productPropertyViews;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class ProductSpuPageReqVO extends PageParam {
|
|||||||
@ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
|
@ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类id", example = "1")
|
@ApiModelProperty(value = "分类编号", example = "1")
|
||||||
private Long categoryId;
|
private Long categoryId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "商品品牌编号", example = "1")
|
@ApiModelProperty(value = "商品品牌编号", example = "1")
|
||||||
|
@ -7,7 +7,6 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@ApiModel("管理后台 - 商品 SPU Response VO")
|
@ApiModel("管理后台 - 商品 SPU Response VO")
|
||||||
@Data
|
@Data
|
||||||
@ -21,4 +20,22 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
|
|||||||
@ApiModelProperty(value = "创建时间")
|
@ApiModelProperty(value = "创建时间")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
// ========== SKU 相关字段 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "库存", required = true, example = "true")
|
||||||
|
private Integer totalStock;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer minPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer maxPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品销量", example = "1024")
|
||||||
|
private Integer salesCount;
|
||||||
|
|
||||||
|
// ========== 统计相关字段 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "点击量", example = "1024")
|
||||||
|
private Integer clickCount;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* 占位符,无时间作用,避免 package 缩进
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.product.controller.app.property;
|
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* 占位符,无时间作用,避免 package 缩进
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.product.controller.app.property.vo.property;
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.controller.app.property.vo.value;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ApiModel("用户 App - 商品属性值的明细 Response VO")
|
||||||
|
@Data
|
||||||
|
public class AppProductPropertyValueDetailRespVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性的编号", required = true, example = "1")
|
||||||
|
private Long propertyId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
|
||||||
|
private Long valueId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
|
||||||
|
private String valueName;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
### 获得订单交易的分页 TODO
|
||||||
|
GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10
|
||||||
|
Authorization: Bearer {{appToken}}
|
||||||
|
tenant-id: {{appTenentId}}
|
||||||
|
|
||||||
|
### 获得商品 SPU 明细
|
||||||
|
GET {{appApi}}/product/spu/get-detail?id=4
|
||||||
|
tenant-id: {{appTenentId}}
|
@ -1,13 +1,22 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.app.spu;
|
package cn.iocoder.yudao.module.product.controller.app.spu;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
|
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||||
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -17,28 +26,54 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
||||||
|
|
||||||
@Api(tags = "用户 APP - 商品spu")
|
@Api(tags = "用户 APP - 商品 SPU")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/product/spu")
|
@RequestMapping("/product/spu")
|
||||||
@Validated
|
@Validated
|
||||||
public class AppProductSpuController {
|
public class AppProductSpuController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductSpuService spuService;
|
private ProductSpuService productSpuService;
|
||||||
|
@Resource
|
||||||
|
private ProductSkuService productSkuService;
|
||||||
|
@Resource
|
||||||
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@ApiOperation("获得商品spu分页")
|
@ApiOperation("获得商品 SPU 分页")
|
||||||
public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
|
public CommonResult<PageResult<AppProductSpuPageItemRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
|
||||||
return success(spuService.getSpuPage(pageVO));
|
PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus());
|
||||||
|
return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/get-detail")
|
||||||
@ApiOperation("获取商品 - 通过商品id")
|
@ApiOperation("获得商品 SPU 明细")
|
||||||
public CommonResult<AppSpuRespVO> getSpu(@RequestParam("spuId") Long spuId) {
|
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||||
AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);
|
public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
|
||||||
return success(appSpuRespVO);
|
// 获得商品 SPU
|
||||||
|
ProductSpuDO spu = productSpuService.getSpu(id);
|
||||||
|
if (spu == null) {
|
||||||
|
throw exception(SPU_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
|
||||||
|
throw exception(SPU_NOT_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询商品 SKU
|
||||||
|
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(),
|
||||||
|
CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
// 查询商品属性
|
||||||
|
List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
|
||||||
|
.getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
|
||||||
|
// 拼接
|
||||||
|
return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("用户 App - 商品 SPU 明细 Response VO")
|
||||||
|
@Data
|
||||||
|
public class AppProductSpuDetailRespVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
// ========== 基本信息 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品名称", required = true, example = "芋道")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "促销语", example = "好吃!")
|
||||||
|
private String sellPoint;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品分类编号", required = true, example = "1")
|
||||||
|
private Long categoryId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品图片的数组", required = true)
|
||||||
|
private List<String> picUrls;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品视频", required = true)
|
||||||
|
private String videoUrl;
|
||||||
|
|
||||||
|
// ========== SKU 相关字段 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
|
||||||
|
private Integer specType;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "是否展示库存", required = true, example = "true")
|
||||||
|
private Boolean showStock;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer minPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer maxPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SKU 数组
|
||||||
|
*/
|
||||||
|
private List<Sku> skus;
|
||||||
|
|
||||||
|
// ========== 统计相关字段 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品销量", required = true, example = "1024")
|
||||||
|
private Integer salesCount;
|
||||||
|
|
||||||
|
@ApiModel("用户 App - 商品 SPU 明细的 SKU 信息")
|
||||||
|
@Data
|
||||||
|
public static class Sku {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品 SKU 编号", example = "1")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品属性数组
|
||||||
|
*/
|
||||||
|
private List<AppProductPropertyValueDetailRespVO> properties;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
|
||||||
|
private Integer marketPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
|
||||||
|
private String picUrl;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "库存", required = true, example = "1")
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
|
||||||
|
private Double weight;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
|
||||||
|
private Double volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("用户 App - 商品 SPU 分页项 Response VO")
|
||||||
|
@Data
|
||||||
|
public class AppProductSpuPageItemRespVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品名称", required = true, example = "芋道")
|
||||||
|
@NotEmpty(message = "商品名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分类编号", required = true)
|
||||||
|
@NotNull(message = "分类编号不能为空")
|
||||||
|
private Long categoryId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品图片的数组", required = true)
|
||||||
|
private List<String> picUrls;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer minPrice;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
|
||||||
|
private Integer maxPrice;
|
||||||
|
|
||||||
|
// ========== 统计相关字段 =========
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "商品销量", example = "1024")
|
||||||
|
private Integer salesCount;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.validation.constraints.AssertTrue;
|
||||||
|
|
||||||
|
@ApiModel("用户 App - 商品 SPU 分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class AppProductSpuPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
public static final String SORT_FIELD_PRICE = "price";
|
||||||
|
public static final String SORT_FIELD_SALES_COUNT = "salesCount";
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分类编号", example = "1")
|
||||||
|
private Long categoryId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "关键字", example = "好看")
|
||||||
|
private String keyword;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序字段", example = "price", notes = "参见 AppSpuPageReqVO.SORT_FIELD_XXX 常量")
|
||||||
|
private String sortField;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "排序方式", example = "true", notes = "true - 升序;false - 降序")
|
||||||
|
private Boolean sortAsc;
|
||||||
|
|
||||||
|
@AssertTrue(message = "排序字段不合法")
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isSortFieldValid() {
|
||||||
|
if (StrUtil.isEmpty(sortField)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
@ApiModel("App - 商品spu分页 Request VO")
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
public class AppSpuPageReqVO extends PageParam {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类id")
|
|
||||||
private Long categoryId;
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@ApiModel("App - 商品spu分页 Request VO")
|
|
||||||
@Data
|
|
||||||
public class AppSpuPageRespVO {
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "主键", required = true, example = "1")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "商品名称")
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "卖点", required = true)
|
|
||||||
@NotNull(message = "卖点不能为空")
|
|
||||||
private String sellPoint;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "描述", required = true)
|
|
||||||
@NotNull(message = "描述不能为空")
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类id", required = true)
|
|
||||||
@NotNull(message = "分类id不能为空")
|
|
||||||
private Long categoryId;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
|
|
||||||
@NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
|
|
||||||
private List<String> picUrls;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "排序字段", required = true)
|
|
||||||
@NotNull(message = "排序字段不能为空")
|
|
||||||
private Integer sort;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "点赞初始人数")
|
|
||||||
private Integer likeCount;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "价格 单位使用:分")
|
|
||||||
private Integer price;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "库存数量")
|
|
||||||
private Integer quantity;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author LuoWenFeng
|
|
||||||
*/
|
|
||||||
@ApiModel("App - 商品spu Response VO")
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class AppSpuRespVO extends ProductSpuRespVO {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +1,21 @@
|
|||||||
package cn.iocoder.yudao.module.product.convert.property;
|
package cn.iocoder.yudao.module.product.convert.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格名称 Convert
|
* 属性项 Convert
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -27,12 +28,21 @@ public interface ProductPropertyConvert {
|
|||||||
|
|
||||||
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
|
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
|
||||||
|
|
||||||
ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
|
|
||||||
|
|
||||||
ProductPropertyRespVO convert(ProductPropertyDO bean);
|
ProductPropertyRespVO convert(ProductPropertyDO bean);
|
||||||
|
|
||||||
List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
|
List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
|
||||||
|
|
||||||
PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
|
PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
|
||||||
|
|
||||||
|
default List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> keys, List<ProductPropertyValueDO> values) {
|
||||||
|
Map<Long, List<ProductPropertyValueDO>> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
|
||||||
|
return CollectionUtils.convertList(keys, key -> {
|
||||||
|
ProductPropertyAndValueRespVO respVO = convert02(key);
|
||||||
|
respVO.setValues(convertList02(valueMap.get(key.getId())));
|
||||||
|
return respVO;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean);
|
||||||
|
List<ProductPropertyAndValueRespVO.Value> convertList02(List<ProductPropertyValueDO> list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
package cn.iocoder.yudao.module.product.convert.propertyvalue;
|
package cn.iocoder.yudao.module.product.convert.propertyvalue;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值 Convert
|
* 属性值 Convert
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -31,6 +38,18 @@ public interface ProductPropertyValueConvert {
|
|||||||
|
|
||||||
PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
|
PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
|
||||||
|
|
||||||
List<ProductPropertyValueDO> convertList03(List<ProductPropertyValueCreateReqVO> list);
|
default List<ProductPropertyValueDetailRespBO> convertList(List<ProductPropertyValueDO> values, List<ProductPropertyDO> keys) {
|
||||||
|
Map<Long, ProductPropertyDO> keyMap = convertMap(keys, ProductPropertyDO::getId);
|
||||||
|
return CollectionUtils.convertList(values, value -> {
|
||||||
|
ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()
|
||||||
|
.setValueId(value.getId()).setValueName(value.getName());
|
||||||
|
// 设置属性项
|
||||||
|
MapUtils.findAndThen(keyMap, value.getPropertyId(),
|
||||||
|
key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));
|
||||||
|
return valueDetail;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProductPropertyValueDetailRespDTO> convertList02(List<ProductPropertyValueDetailRespBO> list);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.product.convert.sku;
|
package cn.iocoder.yudao.module.product.convert.sku;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
@ -10,9 +12,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
|||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
|
|
||||||
@ -32,12 +33,16 @@ public interface ProductSkuConvert {
|
|||||||
|
|
||||||
List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
|
List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
|
||||||
|
|
||||||
List<ProductSkuDO> convertSkuDOList(List<ProductSkuCreateOrUpdateReqVO> list);
|
List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list);
|
||||||
|
|
||||||
|
default List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId, String spuName) {
|
||||||
|
List<ProductSkuDO> result = convertList06(list);
|
||||||
|
result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ProductSkuRespDTO convert02(ProductSkuDO bean);
|
ProductSkuRespDTO convert02(ProductSkuDO bean);
|
||||||
|
|
||||||
List<ProductSkuRespDTO> convertList02(List<ProductSkuDO> list);
|
|
||||||
|
|
||||||
List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list);
|
List<ProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> list);
|
||||||
|
|
||||||
List<ProductSkuRespDTO> convertList04(List<ProductSkuDO> list);
|
List<ProductSkuRespDTO> convertList04(List<ProductSkuDO> list);
|
||||||
@ -66,4 +71,23 @@ public interface ProductSkuConvert {
|
|||||||
return spuIdAndStockMap;
|
return spuIdAndStockMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Collection<Long> convertPropertyValueIds(List<ProductSkuDO> list) {
|
||||||
|
if (CollUtil.isEmpty(list)) {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
|
return list.stream().filter(item -> item.getProperties() != null)
|
||||||
|
.flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
|
||||||
|
.map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
default String buildPropertyKey(ProductSkuDO bean) {
|
||||||
|
if (CollUtil.isEmpty(bean.getProperties())) {
|
||||||
|
return StrUtil.EMPTY;
|
||||||
|
}
|
||||||
|
List<ProductSkuDO.Property> properties = new ArrayList<>(bean.getProperties());
|
||||||
|
properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId));
|
||||||
|
return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,29 @@
|
|||||||
package cn.iocoder.yudao.module.product.convert.spu;
|
package cn.iocoder.yudao.module.product.convert.spu;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品spu Convert
|
* 商品 SPU Convert
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -25,18 +36,73 @@ public interface ProductSpuConvert {
|
|||||||
|
|
||||||
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
|
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
|
||||||
|
|
||||||
ProductSpuRespVO convert(ProductSpuDO bean);
|
List<ProductSpuDO> convertList(List<ProductSpuDO> list);
|
||||||
|
|
||||||
List<ProductSpuRespVO> convertList(List<ProductSpuDO> list);
|
|
||||||
|
|
||||||
PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
|
PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
|
||||||
|
|
||||||
ProductSpuPageReqVO convert(AppSpuPageReqVO bean);
|
ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
|
||||||
|
|
||||||
AppSpuPageRespVO convertAppResp(ProductSpuDO list);
|
|
||||||
|
|
||||||
List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
|
List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
|
||||||
|
|
||||||
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
|
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
|
||||||
|
|
||||||
|
default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus,
|
||||||
|
List<ProductPropertyValueDetailRespBO> propertyValues) {
|
||||||
|
AppProductSpuDetailRespVO spuVO = convert02(spu)
|
||||||
|
.setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
|
||||||
|
spuVO.setSkus(convertList03(skus));
|
||||||
|
// 处理商品属性
|
||||||
|
Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
|
||||||
|
for (int i = 0; i < skus.size(); i++) {
|
||||||
|
List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
|
||||||
|
if (CollUtil.isEmpty(properties)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
|
||||||
|
sku.setProperties(new ArrayList<>(properties.size()));
|
||||||
|
// 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
|
||||||
|
properties.forEach(property -> {
|
||||||
|
ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
|
||||||
|
if (propertyValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sku.getProperties().add(convert03(propertyValue));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return spuVO;
|
||||||
|
}
|
||||||
|
AppProductSpuDetailRespVO convert02(ProductSpuDO spu);
|
||||||
|
List<AppProductSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus);
|
||||||
|
AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
|
||||||
|
|
||||||
|
PageResult<AppProductSpuPageItemRespVO> convertPage02(PageResult<ProductSpuDO> page);
|
||||||
|
|
||||||
|
default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus,
|
||||||
|
List<ProductPropertyValueDetailRespBO> propertyValues) {
|
||||||
|
ProductSpuDetailRespVO spuVO = convert03(spu);
|
||||||
|
spuVO.setSkus(convertList04(skus));
|
||||||
|
// 处理商品属性
|
||||||
|
Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
|
||||||
|
for (int i = 0; i < skus.size(); i++) {
|
||||||
|
List<ProductSkuDO.Property> properties = skus.get(i).getProperties();
|
||||||
|
if (CollUtil.isEmpty(properties)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
|
||||||
|
sku.setProperties(new ArrayList<>(properties.size()));
|
||||||
|
// 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
|
||||||
|
properties.forEach(property -> {
|
||||||
|
ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
|
||||||
|
if (propertyValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sku.getProperties().add(convert04(propertyValue));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return spuVO;
|
||||||
|
}
|
||||||
|
ProductSpuDetailRespVO convert03(ProductSpuDO spu);
|
||||||
|
List<ProductSpuDetailRespVO.Sku> convertList04(List<ProductSkuDO> skus);
|
||||||
|
ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.product.dal.dataobject.property;
|
package cn.iocoder.yudao.module.product.dal.dataobject.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
@ -8,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格名称 DO
|
* 商品属性项 DO
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -28,20 +27,12 @@ public class ProductPropertyDO extends BaseDO {
|
|||||||
@TableId
|
@TableId
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 规格名称
|
* 名称
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 状态
|
|
||||||
*
|
|
||||||
* 枚举 {@link CommonStatusEnum}
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
/**
|
/**
|
||||||
* 备注
|
* 备注
|
||||||
*/
|
*/
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
// TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.product.dal.dataobject.property;
|
package cn.iocoder.yudao.module.product.dal.dataobject.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
@ -9,7 +8,7 @@ import lombok.*;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值 DO
|
* 商品属性值 DO
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -29,21 +28,15 @@ public class ProductPropertyValueDO extends BaseDO {
|
|||||||
@TableId
|
@TableId
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 规格键编号
|
* 属性项的编号
|
||||||
*
|
*
|
||||||
* 关联 {@link ProductPropertyDO#getId()}
|
* 关联 {@link ProductPropertyDO#getId()}
|
||||||
*/
|
*/
|
||||||
private Long propertyId;
|
private Long propertyId;
|
||||||
/**
|
/**
|
||||||
* 规格值名字
|
* 名称
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 状态
|
|
||||||
*
|
|
||||||
* 枚举 {@link CommonStatusEnum}
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
/**
|
/**
|
||||||
* 备注
|
* 备注
|
||||||
*
|
*
|
||||||
|
@ -35,10 +35,6 @@ public class ProductSkuDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
@TableId
|
@TableId
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
|
||||||
* 商品 SKU 名字
|
|
||||||
*/
|
|
||||||
private String name;
|
|
||||||
/**
|
/**
|
||||||
* SPU 编号
|
* SPU 编号
|
||||||
* <p>
|
* <p>
|
||||||
@ -46,7 +42,13 @@ public class ProductSkuDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private Long spuId;
|
private Long spuId;
|
||||||
/**
|
/**
|
||||||
* 规格值数组,JSON 格式
|
* SPU 名字
|
||||||
|
*
|
||||||
|
* 冗余 {@link ProductSkuDO#getSpuName()}
|
||||||
|
*/
|
||||||
|
private String spuName;
|
||||||
|
/**
|
||||||
|
* 属性数组,JSON 格式
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = PropertyTypeHandler.class)
|
@TableField(typeHandler = PropertyTypeHandler.class)
|
||||||
private List<Property> properties;
|
private List<Property> properties;
|
||||||
|
@ -3,31 +3,30 @@ package cn.iocoder.yudao.module.product.dal.mysql.property;
|
|||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* 规格名称 Mapper
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
|
public interface ProductPropertyMapper extends BaseMapperX<ProductPropertyDO> {
|
||||||
|
|
||||||
default PageResult<ProductPropertyDO> selectPage(ProductPropertyPageReqVO reqVO) {
|
default PageResult<ProductPropertyDO> selectPage(ProductPropertyPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyDO>()
|
||||||
.likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
|
.likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
|
||||||
.eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus())
|
|
||||||
.betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
|
.betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
|
||||||
.orderByDesc(ProductPropertyDO::getId));
|
.orderByDesc(ProductPropertyDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default ProductPropertyDO selectByName(String name) {
|
default ProductPropertyDO selectByName(String name) {
|
||||||
return selectOne(new LambdaQueryWrapperX<ProductPropertyDO>()
|
return selectOne(ProductPropertyDO::getName, name);
|
||||||
.eqIfPresent(ProductPropertyDO::getName, name));
|
}
|
||||||
|
|
||||||
|
default List<ProductPropertyDO> selectList(ProductPropertyListReqVO listReqVO) {
|
||||||
|
return selectList(new LambdaQueryWrapperX<ProductPropertyDO>()
|
||||||
|
.eqIfPresent(ProductPropertyDO::getName, listReqVO.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
|
|||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* 规格值 Mapper
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> {
|
public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> {
|
||||||
|
|
||||||
default List<ProductPropertyValueDO> selectListByPropertyId(List<Long> propertyIds) {
|
default List<ProductPropertyValueDO> selectListByPropertyId(Collection<Long> propertyIds) {
|
||||||
return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>()
|
return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>()
|
||||||
.inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
|
.inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
|
||||||
}
|
}
|
||||||
@ -28,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyV
|
|||||||
.eq(ProductPropertyValueDO::getName, name));
|
.eq(ProductPropertyValueDO::getName, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deletePropertyValueByPropertyId(Long propertyId) {
|
default void deleteByPropertyId(Long propertyId) {
|
||||||
delete(new LambdaQueryWrapperX<ProductPropertyValueDO>().eq(ProductPropertyValueDO::getPropertyId, propertyId)
|
delete(new LambdaQueryWrapperX<ProductPropertyValueDO>()
|
||||||
.eq(ProductPropertyValueDO::getDeleted, false));
|
.eq(ProductPropertyValueDO::getPropertyId, propertyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default PageResult<ProductPropertyValueDO> selectPage(ProductPropertyValuePageReqVO reqVO) {
|
default PageResult<ProductPropertyValueDO> selectPage(ProductPropertyValuePageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyValueDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<ProductPropertyValueDO>()
|
||||||
.eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId())
|
.eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId())
|
||||||
.likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName())
|
.likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName())
|
||||||
.eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus())
|
|
||||||
.orderByDesc(ProductPropertyValueDO::getId));
|
.orderByDesc(ProductPropertyValueDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Integer selectCountByPropertyId(Long propertyId) {
|
||||||
|
return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> {
|
|||||||
return selectList(ProductSkuDO::getSpuId, spuId);
|
return selectList(ProductSkuDO::getSpuId, spuId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<ProductSkuDO> selectListBySpuIdAndStatus(Long spuId,
|
||||||
|
Integer status) {
|
||||||
|
return selectList(new LambdaQueryWrapperX<ProductSkuDO>()
|
||||||
|
.eq(ProductSkuDO::getSpuId, spuId)
|
||||||
|
.eqIfPresent(ProductSkuDO::getStatus, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<ProductSkuDO> selectListBySpuId(Collection<Long> spuIds) {
|
||||||
|
return selectList(ProductSkuDO::getSpuId, spuIds);
|
||||||
|
}
|
||||||
|
|
||||||
default void deleteBySpuId(Long spuId) {
|
default void deleteBySpuId(Long spuId) {
|
||||||
delete(new LambdaQueryWrapperX<ProductSkuDO>().eq(ProductSkuDO::getSpuId, spuId));
|
delete(new LambdaQueryWrapperX<ProductSkuDO>().eq(ProductSkuDO::getSpuId, spuId));
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +46,19 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
|||||||
.orderByDesc(ProductSpuDO::getSort));
|
.orderByDesc(ProductSpuDO::getSort));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default PageResult<ProductSpuDO> selectPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
|
||||||
|
LambdaQueryWrapperX<ProductSpuDO> query = new LambdaQueryWrapperX<ProductSpuDO>()
|
||||||
|
.eqIfPresent(ProductSpuDO::getCategoryId, pageReqVO.getCategoryId())
|
||||||
|
.eqIfPresent(ProductSpuDO::getStatus, status);
|
||||||
|
// 排序逻辑
|
||||||
|
if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
|
||||||
|
query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getMaxPrice);
|
||||||
|
} else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
|
||||||
|
query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount);
|
||||||
|
}
|
||||||
|
return selectPage(pageReqVO, query);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新商品 SPU 库存
|
* 更新商品 SPU 库存
|
||||||
*
|
*
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* trade 模块,主要实现交易相关功能
|
* trade 模块,主要实现交易相关功能
|
||||||
* 例如:订单、退款、购物车等功能。
|
* 例如:订单、退款、购物车等功能。
|
||||||
*
|
*
|
||||||
* 1. Controller URL:以 /trade/ 开头,避免和其它 Module 冲突
|
* 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突
|
||||||
* 2. DataObject 表名:以 trade_ 开头,方便在数据库中区分
|
* 2. DataObject 表名:以 product_ 开头,方便在数据库中区分
|
||||||
*/
|
*/
|
||||||
package cn.iocoder.yudao.module.product;
|
package cn.iocoder.yudao.module.product;
|
||||||
|
@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
|
|||||||
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,12 +46,19 @@ public interface ProductCategoryService {
|
|||||||
ProductCategoryDO getCategory(Long id);
|
ProductCategoryDO getCategory(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品分类列表
|
* 校验商品分类
|
||||||
*
|
*
|
||||||
* @param ids 编号
|
* @param id 分类编号
|
||||||
* @return 商品分类列表
|
|
||||||
*/
|
*/
|
||||||
List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids);
|
void validateCategory(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得商品分类的层级
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 商品分类的层级
|
||||||
|
*/
|
||||||
|
Integer getCategoryLevel(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品分类列表
|
* 获得商品分类列表
|
||||||
@ -62,14 +68,6 @@ public interface ProductCategoryService {
|
|||||||
*/
|
*/
|
||||||
List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO);
|
List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证选择的商品分类的级别是否合法
|
|
||||||
* 例如说,商品发布的时候,必须在第 3 级别
|
|
||||||
*
|
|
||||||
* @param id 分类编号
|
|
||||||
*/
|
|
||||||
void validateCategoryLevel(Long id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得开启状态的商品分类列表
|
* 获得开启状态的商品分类列表
|
||||||
*
|
*
|
||||||
|
@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -90,31 +89,40 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validateCategoryLevel(Long id) {
|
|
||||||
// TODO @芋艿:在看看,杂能优化下
|
|
||||||
Long parentId = id;
|
|
||||||
int i = 2;
|
|
||||||
for (; i >= 0; --i) {
|
|
||||||
ProductCategoryDO category = productCategoryMapper.selectById(parentId);
|
|
||||||
parentId = category.getParentId();
|
|
||||||
if(Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL)){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL) || i != 0) {
|
|
||||||
throw exception(CATEGORY_LEVEL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProductCategoryDO getCategory(Long id) {
|
public ProductCategoryDO getCategory(Long id) {
|
||||||
return productCategoryMapper.selectById(id);
|
return productCategoryMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids) {
|
public void validateCategory(Long id) {
|
||||||
return productCategoryMapper.selectBatchIds(ids);
|
ProductCategoryDO category = productCategoryMapper.selectById(id);
|
||||||
|
if (category == null) {
|
||||||
|
throw exception(CATEGORY_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
|
||||||
|
throw exception(CATEGORY_DISABLED, category.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getCategoryLevel(Long id) {
|
||||||
|
if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int level = 1;
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
ProductCategoryDO category = productCategoryMapper.selectById(id);
|
||||||
|
// 如果没有父节点,break 结束
|
||||||
|
if (category == null
|
||||||
|
|| Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 继续递归父节点
|
||||||
|
level++;
|
||||||
|
id = category.getParentId();
|
||||||
|
}
|
||||||
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.property;
|
package cn.iocoder.yudao.module.product.service.property;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
|
|
||||||
@ -10,14 +9,15 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格名称 Service 接口
|
* 商品属性项 Service 接口
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface ProductPropertyService {
|
public interface ProductPropertyService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建规格名称
|
* 创建属性项
|
||||||
|
* 注意,如果已经存在该属性项,直接返回它的编号即可
|
||||||
*
|
*
|
||||||
* @param createReqVO 创建信息
|
* @param createReqVO 创建信息
|
||||||
* @return 编号
|
* @return 编号
|
||||||
@ -25,56 +25,48 @@ public interface ProductPropertyService {
|
|||||||
Long createProperty(@Valid ProductPropertyCreateReqVO createReqVO);
|
Long createProperty(@Valid ProductPropertyCreateReqVO createReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新规格名称
|
* 更新属性项
|
||||||
*
|
*
|
||||||
* @param updateReqVO 更新信息
|
* @param updateReqVO 更新信息
|
||||||
*/
|
*/
|
||||||
void updateProperty(@Valid ProductPropertyUpdateReqVO updateReqVO);
|
void updateProperty(@Valid ProductPropertyUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除规格名称
|
* 删除属性项
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
*/
|
*/
|
||||||
void deleteProperty(Long id);
|
void deleteProperty(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得规格名称列表
|
* 获得属性项列表
|
||||||
* @param listReqVO 集合查询
|
* @param listReqVO 集合查询
|
||||||
* @return 规格名称集合
|
* @return 属性项集合
|
||||||
*/
|
*/
|
||||||
List<ProductPropertyRespVO> getPropertyList(ProductPropertyListReqVO listReqVO);
|
List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取属性名称分页
|
* 获取属性名称分页
|
||||||
*
|
*
|
||||||
* @param pageReqVO 分页条件
|
* @param pageReqVO 分页条件
|
||||||
* @return 规格名称分页
|
* @return 属性项分页
|
||||||
*/
|
*/
|
||||||
PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO);
|
PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得指定编号的规格名称
|
* 获得指定编号的属性项
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 规格名称
|
* @return 属性项
|
||||||
*/
|
*/
|
||||||
ProductPropertyRespVO getProperty(Long id);
|
ProductPropertyDO getProperty(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据规格属性编号的集合,获得对应的规格 + 规格值的集合
|
* 根据属性项的编号的集合,获得对应的属性项数组
|
||||||
*
|
*
|
||||||
* @param ids 规格编号的集合
|
* @param ids 属性项的编号的集合
|
||||||
* @return 对应的规格
|
* @return 属性项数组
|
||||||
*/
|
*/
|
||||||
List<ProductPropertyRespVO> getPropertyList(Collection<Long> ids);
|
List<ProductPropertyDO> getPropertyList(Collection<Long> ids);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得规格名称 + 值的列表
|
|
||||||
*
|
|
||||||
* @param listReqVO 列表查询
|
|
||||||
* @return 规格名称 + 值的列表
|
|
||||||
*/
|
|
||||||
List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.property;
|
package cn.iocoder.yudao.module.product.service.property;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
|
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
|
||||||
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper;
|
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper;
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -18,15 +17,12 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_EXISTS;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格名称 Service 实现类
|
* 商品属性项 Service 实现类
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -38,15 +34,18 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
|
|||||||
private ProductPropertyMapper productPropertyMapper;
|
private ProductPropertyMapper productPropertyMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductPropertyValueMapper productPropertyValueMapper;
|
@Lazy // 延迟加载,解决循环依赖问题
|
||||||
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
|
public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
|
||||||
// 校验存在
|
// 如果已经添加过该属性项,直接返回
|
||||||
if (productPropertyMapper.selectByName(createReqVO.getName()) != null) {
|
ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName());
|
||||||
throw exception(PROPERTY_EXISTS);
|
if (dbProperty != null) {
|
||||||
|
return dbProperty.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入
|
// 插入
|
||||||
ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO);
|
ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO);
|
||||||
productPropertyMapper.insert(property);
|
productPropertyMapper.insert(property);
|
||||||
@ -57,12 +56,14 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateProperty(ProductPropertyUpdateReqVO updateReqVO) {
|
public void updateProperty(ProductPropertyUpdateReqVO updateReqVO) {
|
||||||
// 校验存在
|
validatePropertyExists(updateReqVO.getId());
|
||||||
this.validatePropertyExists(updateReqVO.getId());
|
// 校验名字重复
|
||||||
ProductPropertyDO productPropertyDO = productPropertyMapper.selectByName(updateReqVO.getName());
|
ProductPropertyDO productPropertyDO = productPropertyMapper.selectByName(updateReqVO.getName());
|
||||||
if (productPropertyDO != null && !productPropertyDO.getId().equals(updateReqVO.getId())) {
|
if (productPropertyDO != null &&
|
||||||
|
ObjUtil.notEqual(productPropertyDO.getId(), updateReqVO.getId())) {
|
||||||
throw exception(PROPERTY_EXISTS);
|
throw exception(PROPERTY_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新
|
// 更新
|
||||||
ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
|
ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
|
||||||
productPropertyMapper.updateById(updateObj);
|
productPropertyMapper.updateById(updateObj);
|
||||||
@ -71,11 +72,16 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
|
|||||||
@Override
|
@Override
|
||||||
public void deleteProperty(Long id) {
|
public void deleteProperty(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
this.validatePropertyExists(id);
|
validatePropertyExists(id);
|
||||||
|
// 校验其下是否有规格值
|
||||||
|
if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) {
|
||||||
|
throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
productPropertyMapper.deleteById(id);
|
productPropertyMapper.deleteById(id);
|
||||||
//同步删除属性值
|
// 同步删除属性值
|
||||||
productPropertyValueMapper.deletePropertyValueByPropertyId(id);
|
productPropertyValueService.deletePropertyValueByPropertyId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePropertyExists(Long id) {
|
private void validatePropertyExists(Long id) {
|
||||||
@ -85,41 +91,23 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductPropertyRespVO> getPropertyList(ProductPropertyListReqVO listReqVO) {
|
public List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO) {
|
||||||
return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectList(new LambdaQueryWrapperX<ProductPropertyDO>()
|
return productPropertyMapper.selectList(listReqVO);
|
||||||
.likeIfPresent(ProductPropertyDO::getName, listReqVO.getName())
|
|
||||||
.eqIfPresent(ProductPropertyDO::getStatus, listReqVO.getStatus())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<ProductPropertyRespVO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
|
public PageResult<ProductPropertyDO> getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
|
||||||
//获取属性列表
|
return productPropertyMapper.selectPage(pageReqVO);
|
||||||
PageResult<ProductPropertyDO> pageResult = productPropertyMapper.selectPage(pageReqVO);
|
|
||||||
return ProductPropertyConvert.INSTANCE.convertPage(pageResult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProductPropertyRespVO getProperty(Long id) {
|
public ProductPropertyDO getProperty(Long id) {
|
||||||
ProductPropertyDO property = productPropertyMapper.selectById(id);
|
return productPropertyMapper.selectById(id);
|
||||||
return ProductPropertyConvert.INSTANCE.convert(property);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductPropertyRespVO> getPropertyList(Collection<Long> ids) {
|
public List<ProductPropertyDO> getPropertyList(Collection<Long> ids) {
|
||||||
return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids));
|
return productPropertyMapper.selectBatchIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ProductPropertyAndValueRespVO> getPropertyAndValueList(ProductPropertyListReqVO listReqVO) {
|
|
||||||
List<ProductPropertyRespVO> propertyList = getPropertyList(listReqVO);
|
|
||||||
|
|
||||||
// 查询属性值
|
|
||||||
List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.selectListByPropertyId(CollectionUtils.convertList(propertyList, ProductPropertyRespVO::getId));
|
|
||||||
Map<Long, List<ProductPropertyValueDO>> valueDOMap = CollectionUtils.convertMultiMap(valueDOList, ProductPropertyValueDO::getPropertyId);
|
|
||||||
return CollectionUtils.convertList(propertyList, m -> {
|
|
||||||
ProductPropertyAndValueRespVO productPropertyAndValueRespVO = ProductPropertyConvert.INSTANCE.convert(m);
|
|
||||||
productPropertyAndValueRespVO.setValues(ProductPropertyValueConvert.INSTANCE.convertList(valueDOMap.get(m.getId())));
|
|
||||||
return productPropertyAndValueRespVO;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,22 +3,23 @@ package cn.iocoder.yudao.module.product.service.property;
|
|||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* 商品属性值 Service 接口
|
||||||
* 规格值 Service 接口
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @author LuoWenFeng
|
* @author LuoWenFeng
|
||||||
*/
|
*/
|
||||||
public interface ProductPropertyValueService {
|
public interface ProductPropertyValueService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建规格值
|
* 创建属性值
|
||||||
|
* 注意,如果已经存在该属性值,直接返回它的编号即可
|
||||||
*
|
*
|
||||||
* @param createReqVO 创建信息
|
* @param createReqVO 创建信息
|
||||||
* @return 编号
|
* @return 编号
|
||||||
@ -26,40 +27,64 @@ public interface ProductPropertyValueService {
|
|||||||
Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO);
|
Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新规格值
|
* 更新属性值
|
||||||
*
|
*
|
||||||
* @param updateReqVO 更新信息
|
* @param updateReqVO 更新信息
|
||||||
*/
|
*/
|
||||||
void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO);
|
void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除规格值
|
* 删除属性值
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
*/
|
*/
|
||||||
void deletePropertyValue(Long id);
|
void deletePropertyValue(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得规格值
|
* 获得属性值
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 规格名称
|
* @return 属性值
|
||||||
*/
|
*/
|
||||||
ProductPropertyValueRespVO getPropertyValue(Long id);
|
ProductPropertyValueDO getPropertyValue(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得规格值
|
* 根据属性项编号数组,获得属性值列表
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param propertyIds 属性项目编号数组
|
||||||
* @return 规格名称
|
* @return 属性值列表
|
||||||
*/
|
*/
|
||||||
List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id);
|
List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取规格值 分页
|
* 根据编号数组,获得属性值列表
|
||||||
|
*
|
||||||
|
* @param ids 编号数组
|
||||||
|
* @return 属性值明细列表
|
||||||
|
*/
|
||||||
|
List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据属性项编号,活的属性值数量
|
||||||
|
*
|
||||||
|
* @param propertyId 属性项编号数
|
||||||
|
* @return 属性值数量
|
||||||
|
*/
|
||||||
|
Integer getPropertyValueCountByPropertyId(Long propertyId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取属性值的分页
|
||||||
*
|
*
|
||||||
* @param pageReqVO 查询条件
|
* @param pageReqVO 查询条件
|
||||||
* @return
|
* @return 属性值的分页
|
||||||
*/
|
*/
|
||||||
PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO);
|
PageResult<ProductPropertyValueDO> getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定属性项编号下的属性值们
|
||||||
|
*
|
||||||
|
* @param propertyId 属性项的编号
|
||||||
|
*/
|
||||||
|
void deletePropertyValueByPropertyId(Long propertyId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,31 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.property;
|
package cn.iocoder.yudao.module.product.service.property;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
|
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
|
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值 Service 实现类
|
* 商品属性值 Service 实现类
|
||||||
*
|
*
|
||||||
* @author LuoWenFeng
|
* @author LuoWenFeng
|
||||||
*/
|
*/
|
||||||
@ -31,45 +36,92 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
|
|||||||
@Resource
|
@Resource
|
||||||
private ProductPropertyValueMapper productPropertyValueMapper;
|
private ProductPropertyValueMapper productPropertyValueMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy // 延迟加载,避免循环依赖
|
||||||
|
private ProductPropertyService productPropertyService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) {
|
public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) {
|
||||||
if (productPropertyValueMapper.selectByName(createReqVO.getPropertyId(), createReqVO.getName()) != null) {
|
// 如果已经添加过该属性值,直接返回
|
||||||
throw exception(PROPERTY_VALUE_EXISTS);
|
ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName(
|
||||||
|
createReqVO.getPropertyId(), createReqVO.getName());
|
||||||
|
if (dbValue != null) {
|
||||||
|
return dbValue.getId();
|
||||||
}
|
}
|
||||||
ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(createReqVO);
|
|
||||||
productPropertyValueMapper.insert(convert);
|
// 新增
|
||||||
return convert.getId();
|
ProductPropertyValueDO value = ProductPropertyValueConvert.INSTANCE.convert(createReqVO);
|
||||||
|
productPropertyValueMapper.insert(value);
|
||||||
|
return value.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO) {
|
public void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO) {
|
||||||
ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName(updateReqVO.getPropertyId(), updateReqVO.getName());
|
validatePropertyValueExists(updateReqVO.getId());
|
||||||
|
// 校验名字唯一
|
||||||
|
ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName
|
||||||
|
(updateReqVO.getPropertyId(), updateReqVO.getName());
|
||||||
if (productPropertyValueDO != null && !productPropertyValueDO.getId().equals(updateReqVO.getId())) {
|
if (productPropertyValueDO != null && !productPropertyValueDO.getId().equals(updateReqVO.getId())) {
|
||||||
throw exception(PROPERTY_VALUE_EXISTS);
|
throw exception(PROPERTY_VALUE_EXISTS);
|
||||||
}
|
}
|
||||||
ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
|
|
||||||
productPropertyValueMapper.updateById(convert);
|
// 更新
|
||||||
|
ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
|
||||||
|
productPropertyValueMapper.updateById(updateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePropertyValue(Long id) {
|
public void deletePropertyValue(Long id) {
|
||||||
|
validatePropertyValueExists(id);
|
||||||
productPropertyValueMapper.deleteById(id);
|
productPropertyValueMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void validatePropertyValueExists(Long id) {
|
||||||
public ProductPropertyValueRespVO getPropertyValue(Long id) {
|
if (productPropertyValueMapper.selectById(id) == null) {
|
||||||
ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectOne(new LambdaQueryWrapper<ProductPropertyValueDO>()
|
throw exception(PROPERTY_VALUE_NOT_EXISTS);
|
||||||
.eq(ProductPropertyValueDO::getId, id));
|
}
|
||||||
return ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueDO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductPropertyValueRespVO> getPropertyValueListByPropertyId(List<Long> id) {
|
public ProductPropertyValueDO getPropertyValue(Long id) {
|
||||||
return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", id));
|
return productPropertyValueMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<ProductPropertyValueRespVO> getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO) {
|
public List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds) {
|
||||||
return ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueMapper.selectPage(pageReqVO));
|
return productPropertyValueMapper.selectListByPropertyId(propertyIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids) {
|
||||||
|
// 获得属性值列表
|
||||||
|
if (CollUtil.isEmpty(ids)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<ProductPropertyValueDO> values = productPropertyValueMapper.selectBatchIds(ids);
|
||||||
|
if (CollUtil.isEmpty(values)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// 获得属性项列表
|
||||||
|
List<ProductPropertyDO> keys = productPropertyService.getPropertyList(
|
||||||
|
convertSet(values, ProductPropertyValueDO::getPropertyId));
|
||||||
|
// 组装明细
|
||||||
|
return ProductPropertyValueConvert.INSTANCE.convertList(values, keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getPropertyValueCountByPropertyId(Long propertyId) {
|
||||||
|
return productPropertyValueMapper.selectCountByPropertyId(propertyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<ProductPropertyValueDO> getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO) {
|
||||||
|
return productPropertyValueMapper.selectPage(pageReqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deletePropertyValueByPropertyId(Long propertyId) {
|
||||||
|
productPropertyValueMapper.deleteByPropertyId(propertyId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package cn.iocoder.yudao.module.product.service.property.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品属性项的明细 Response BO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProductPropertyValueDetailRespBO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性的编号
|
||||||
|
*/
|
||||||
|
private Long propertyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性的名称
|
||||||
|
*/
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性值的编号
|
||||||
|
*/
|
||||||
|
private Long valueId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性值的名称
|
||||||
|
*/
|
||||||
|
private String valueName;
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku;
|
|||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -49,23 +50,25 @@ public interface ProductSkuService {
|
|||||||
*
|
*
|
||||||
* @param list sku组合的集合
|
* @param list sku组合的集合
|
||||||
*/
|
*/
|
||||||
void validateSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType);
|
void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量创建 SKU
|
* 批量创建 SKU
|
||||||
*
|
*
|
||||||
* @param spuId 商品 SPU 编号
|
* @param spuId 商品 SPU 编号
|
||||||
|
* @param spuName 商品 SPU 名称
|
||||||
* @param list SKU 对象集合
|
* @param list SKU 对象集合
|
||||||
*/
|
*/
|
||||||
void createSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
|
void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 SPU 编号,批量更新它的 SKU 信息
|
* 根据 SPU 编号,批量更新它的 SKU 信息
|
||||||
*
|
*
|
||||||
* @param spuId SPU 编码
|
* @param spuId SPU 编码
|
||||||
|
* @param spuName 商品 SPU 名称
|
||||||
* @param skus SKU 的集合
|
* @param skus SKU 的集合
|
||||||
*/
|
*/
|
||||||
void updateSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus);
|
void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新 SKU 库存(增量)
|
* 更新 SKU 库存(增量)
|
||||||
@ -77,20 +80,30 @@ public interface ProductSkuService {
|
|||||||
void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
|
void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品 sku 集合
|
* 获得商品 SKU 集合
|
||||||
*
|
*
|
||||||
* @param spuId spu 编号
|
* @param spuId spu 编号
|
||||||
* @return 商品sku 集合
|
* @return 商品sku 集合
|
||||||
*/
|
*/
|
||||||
List<ProductSkuDO> getSkusBySpuId(Long spuId);
|
List<ProductSkuDO> getSkuListBySpuId(Long spuId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得 spu 对应的 sku 集合
|
* 基于 SPU 编号和状态,获得商品 SKU 集合
|
||||||
|
*
|
||||||
|
* @param spuId SPU 编号
|
||||||
|
* @param status 状态
|
||||||
|
* @return 商品 SKU 集合
|
||||||
|
*/
|
||||||
|
List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId,
|
||||||
|
@Nullable Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 spu 对应的 SKU 集合
|
||||||
*
|
*
|
||||||
* @param spuIds spu 编码集合
|
* @param spuIds spu 编码集合
|
||||||
* @return 商品 sku 集合
|
* @return 商品 sku 集合
|
||||||
*/
|
*/
|
||||||
List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds);
|
List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 spuId 删除 sku 信息
|
* 通过 spuId 删除 sku 信息
|
||||||
@ -104,7 +117,6 @@ public interface ProductSkuService {
|
|||||||
*
|
*
|
||||||
* @return SKU 数组
|
* @return SKU 数组
|
||||||
*/
|
*/
|
||||||
List<ProductSkuDO> getSkusByAlarmStock();
|
List<ProductSkuDO> getSkuListByAlarmStock();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.sku;
|
package cn.iocoder.yudao.module.product.service.sku;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
|
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
|
||||||
import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
|
import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
|
||||||
@ -25,6 +25,7 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
@ -78,22 +79,24 @@ public class ProductSkuServiceImpl implements ProductSkuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateSkus(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) {
|
public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) {
|
||||||
// 非多规格,不需要校验
|
// 非多规格,不需要校验
|
||||||
if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
|
if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1、校验规格属性存在
|
// 1、校验属性项存在
|
||||||
Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
|
Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null)
|
||||||
.map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合
|
.flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
|
||||||
List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyList(propertyIds);
|
.map(ProductSkuBaseVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyIds);
|
||||||
if (propertyList.size() != propertyIds.size()) {
|
if (propertyList.size() != propertyIds.size()) {
|
||||||
throw exception(PROPERTY_NOT_EXISTS);
|
throw exception(PROPERTY_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId
|
// 2. 校验,一个 SKU 下,没有重复的属性。校验方式是,遍历每个 SKU ,看看是否有重复的属性 propertyId
|
||||||
Map<Long, ProductPropertyValueRespVO> propertyValueMap = CollectionUtils.convertMap(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyIds)), ProductPropertyValueRespVO::getId);
|
Map<Long, ProductPropertyValueDO> propertyValueMap = convertMap(productPropertyValueService.getPropertyValueListByPropertyId(propertyIds), ProductPropertyValueDO::getId);
|
||||||
skus.forEach(sku -> {
|
skus.forEach(sku -> {
|
||||||
Set<Long> skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId());
|
Set<Long> skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId());
|
||||||
if (skuPropertyIds.size() != sku.getProperties().size()) {
|
if (skuPropertyIds.size() != sku.getProperties().size()) {
|
||||||
@ -101,7 +104,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. 再校验,每个 Sku 的规格值的数量,是一致的。
|
// 3. 再校验,每个 Sku 的属性值的数量,是一致的。
|
||||||
int attrValueIdsSize = skus.get(0).getProperties().size();
|
int attrValueIdsSize = skus.get(0).getProperties().size();
|
||||||
for (int i = 1; i < skus.size(); i++) {
|
for (int i = 1; i < skus.size(); i++) {
|
||||||
if (attrValueIdsSize != skus.get(i).getProperties().size()) {
|
if (attrValueIdsSize != skus.get(i).getProperties().size()) {
|
||||||
@ -119,21 +122,23 @@ public class ProductSkuServiceImpl implements ProductSkuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
|
public void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
|
||||||
// 批量插入 SKU
|
productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId, spuName));
|
||||||
List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList);
|
|
||||||
skuDOList.forEach(v -> v.setSpuId(spuId));
|
|
||||||
productSkuMapper.insertBatch(skuDOList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductSkuDO> getSkusBySpuId(Long spuId) {
|
public List<ProductSkuDO> getSkuListBySpuId(Long spuId) {
|
||||||
return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuId);
|
return productSkuMapper.selectListBySpuId(spuId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds) {
|
public List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId, Integer status) {
|
||||||
return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuIds);
|
return productSkuMapper.selectListBySpuIdAndStatus(spuId, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) {
|
||||||
|
return productSkuMapper.selectListBySpuId(spuIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -142,59 +147,44 @@ public class ProductSkuServiceImpl implements ProductSkuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductSkuDO> getSkusByAlarmStock() {
|
public List<ProductSkuDO> getSkuListByAlarmStock() {
|
||||||
return productSkuMapper.selectListByAlarmStock();
|
return productSkuMapper.selectListByAlarmStock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) {
|
public void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) {
|
||||||
// 查询 SPU 下已经存在的 SKU 的集合
|
// 构建属性与 SKU 的映射关系;
|
||||||
List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuId(spuId);
|
Map<String, Long> existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId),
|
||||||
// 构建规格与 SKU 的映射关系;
|
ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId);
|
||||||
// TODO @luowenfeng: 可以下 existsSkuMap2; 会简洁一点; 另外, 可以考虑抽一个小方法, 用于 Properties 生成一个串; 这样 177 也可以复用了
|
|
||||||
Map<String, Long> existsSkuMap = existsSkus.stream()
|
|
||||||
.map(v -> {
|
|
||||||
String collect = v.getProperties() == null? "null": v.getProperties()
|
|
||||||
.stream()
|
|
||||||
.map(m -> String.valueOf(m.getValueId()))
|
|
||||||
.collect(Collectors.joining());
|
|
||||||
return String.join("-", collect, String.valueOf(v.getId()));
|
|
||||||
})
|
|
||||||
.collect(Collectors.toMap(v -> v.split("-")[0], v -> Long.valueOf(v.split("-")[1])));
|
|
||||||
|
|
||||||
// 拆分三个集合,新插入的、需要更新的、需要删除的
|
// 拆分三个集合,新插入的、需要更新的、需要删除的
|
||||||
List<ProductSkuDO> insertSkus = new ArrayList<>();
|
List<ProductSkuDO> insertSkus = new ArrayList<>();
|
||||||
List<ProductSkuDO> updateSkus = new ArrayList<>();
|
List<ProductSkuDO> updateSkus = new ArrayList<>();
|
||||||
List<Long> deleteSkus = new ArrayList<>();
|
List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null, spuName);
|
||||||
|
allUpdateSkus.forEach(sku -> {
|
||||||
List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus);
|
String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku);
|
||||||
allUpdateSkus.forEach(p -> {
|
|
||||||
String propertiesKey = p.getProperties() == null? "null": p.getProperties().stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
|
|
||||||
// 1、找得到的,进行更新
|
// 1、找得到的,进行更新
|
||||||
if (existsSkuMap.containsKey(propertiesKey)) {
|
Long existsSkuId = existsSkuMap.remove(propertiesKey);
|
||||||
updateSkus.add(p);
|
if (existsSkuId != null) {
|
||||||
existsSkuMap.remove(propertiesKey);
|
sku.setId(existsSkuId);
|
||||||
|
updateSkus.add(sku);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 2、找不到,进行插入
|
// 2、找不到,进行插入
|
||||||
p.setSpuId(spuId);
|
sku.setSpuId(spuId);
|
||||||
insertSkus.add(p);
|
insertSkus.add(sku);
|
||||||
});
|
});
|
||||||
// 3、多余的,删除
|
|
||||||
if(!existsSkuMap.isEmpty()){
|
|
||||||
deleteSkus = new ArrayList<>(existsSkuMap.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4、执行修改 Sku
|
// 执行最终的批量操作
|
||||||
if (!insertSkus.isEmpty()) {
|
if (CollUtil.isNotEmpty(insertSkus)) {
|
||||||
productSkuMapper.insertBatch(insertSkus);
|
productSkuMapper.insertBatch(insertSkus);
|
||||||
}
|
}
|
||||||
if (!updateSkus.isEmpty()) {
|
if (CollUtil.isNotEmpty(updateSkus)) {
|
||||||
updateSkus.forEach(p -> productSkuMapper.updateById(p));
|
updateSkus.forEach(sku -> productSkuMapper.updateById(sku));
|
||||||
}
|
}
|
||||||
if (!deleteSkus.isEmpty()) {
|
if (CollUtil.isNotEmpty(existsSkuMap)) {
|
||||||
productSkuMapper.deleteBatchIds(deleteSkus);
|
productSkuMapper.deleteBatchIds(existsSkuMap.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -42,21 +41,13 @@ public interface ProductSpuService {
|
|||||||
*/
|
*/
|
||||||
void deleteSpu(Long id);
|
void deleteSpu(Long id);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得商品 SPU 详情
|
|
||||||
*
|
|
||||||
* @param id 编号
|
|
||||||
* @return 商品 SPU
|
|
||||||
*/
|
|
||||||
ProductSpuDetailRespVO getSpuDetail(Long id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品 SPU
|
* 获得商品 SPU
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 商品 SPU
|
* @return 商品 SPU
|
||||||
*/
|
*/
|
||||||
ProductSpuRespVO getSpu(Long id);
|
ProductSpuDO getSpu(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品 SPU 列表
|
* 获得商品 SPU 列表
|
||||||
@ -89,15 +80,16 @@ public interface ProductSpuService {
|
|||||||
* @param pageReqVO 分页查询
|
* @param pageReqVO 分页查询
|
||||||
* @return 商品spu分页
|
* @return 商品spu分页
|
||||||
*/
|
*/
|
||||||
PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO);
|
PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得商品 SPU 分页
|
* 获得商品 SPU 分页
|
||||||
*
|
*
|
||||||
* @param pageReqVO 分页查询
|
* @param pageReqVO 分页查询
|
||||||
* @return 商品spu分页
|
* @param status 状态
|
||||||
|
* @return 商品 SPU 分页
|
||||||
*/
|
*/
|
||||||
PageResult<AppSpuPageRespVO> getSpuPage(AppSpuPageReqVO pageReqVO);
|
PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新商品 SPU 库存(增量)
|
* 更新商品 SPU 库存(增量)
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.spu;
|
package cn.iocoder.yudao.module.product.service.spu;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
|
||||||
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
|
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
|
||||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
|
|
||||||
import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
|
import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
|
||||||
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
|
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
|
||||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
|
||||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
|
||||||
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -30,11 +21,15 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
import java.util.stream.Collectors;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品 SPU Service 实现类
|
* 商品 SPU Service 实现类
|
||||||
@ -48,68 +43,85 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||||||
@Resource
|
@Resource
|
||||||
private ProductSpuMapper productSpuMapper;
|
private ProductSpuMapper productSpuMapper;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ProductCategoryService categoryService;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Lazy // 循环依赖,避免报错
|
@Lazy // 循环依赖,避免报错
|
||||||
private ProductSkuService productSkuService;
|
private ProductSkuService productSkuService;
|
||||||
@Resource
|
@Resource
|
||||||
private ProductPropertyService productPropertyService;
|
|
||||||
@Resource
|
|
||||||
private ProductPropertyValueService productPropertyValueService;
|
|
||||||
@Resource
|
|
||||||
private ProductBrandService brandService;
|
private ProductBrandService brandService;
|
||||||
|
@Resource
|
||||||
|
private ProductCategoryService categoryService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
|
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
|
||||||
// 校验分类
|
// 校验分类
|
||||||
categoryService.validateCategoryLevel(createReqVO.getCategoryId());
|
validateCategory(createReqVO.getCategoryId());
|
||||||
// 校验品牌
|
// 校验品牌
|
||||||
brandService.validateProductBrand(createReqVO.getBrandId());
|
brandService.validateProductBrand(createReqVO.getBrandId());
|
||||||
// 校验SKU
|
// 校验SKU
|
||||||
List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();
|
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
|
||||||
productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType());
|
productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
|
||||||
|
|
||||||
// 插入 SPU
|
// 插入 SPU
|
||||||
ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
|
ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
|
||||||
spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
initSpuFromSkus(spu, skuSaveReqList);
|
||||||
spu.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
||||||
spu.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
||||||
spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
|
||||||
productSpuMapper.insert(spu);
|
productSpuMapper.insert(spu);
|
||||||
// 插入 SKU
|
// 插入 SKU
|
||||||
productSkuService.createSkus(spu.getId(), skuCreateReqList);
|
productSkuService.createSkuList(spu.getId(), spu.getName(), skuSaveReqList);
|
||||||
// 返回
|
// 返回
|
||||||
return spu.getId();
|
return spu.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
|
public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
|
||||||
// 校验 SPU 是否存在
|
// 校验 SPU 是否存在
|
||||||
validateSpuExists(updateReqVO.getId());
|
validateSpuExists(updateReqVO.getId());
|
||||||
// 校验分类
|
// 校验分类
|
||||||
categoryService.validateCategoryLevel(updateReqVO.getCategoryId());
|
validateCategory(updateReqVO.getCategoryId());
|
||||||
// 校验品牌
|
// 校验品牌
|
||||||
brandService.validateProductBrand(updateReqVO.getBrandId());
|
brandService.validateProductBrand(updateReqVO.getBrandId());
|
||||||
// 校验SKU
|
// 校验SKU
|
||||||
List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus();
|
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus();
|
||||||
productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType());
|
productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
|
||||||
|
|
||||||
// 更新 SPU
|
// 更新 SPU
|
||||||
ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
|
ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
|
||||||
updateObj.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
initSpuFromSkus(updateObj, skuSaveReqList);
|
||||||
updateObj.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
||||||
updateObj.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
||||||
updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
|
||||||
productSpuMapper.updateById(updateObj);
|
productSpuMapper.updateById(updateObj);
|
||||||
// 批量更新 SKU
|
// 批量更新 SKU
|
||||||
productSkuService.updateSkus(updateObj.getId(), updateReqVO.getSkus());
|
productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于 SKU 的信息,初始化 SPU 的信息
|
||||||
|
* 主要是计数相关的字段,例如说市场价、最大最小价、库存等等
|
||||||
|
*
|
||||||
|
* @param spu 商品 SPU
|
||||||
|
* @param skus 商品 SKU 数组
|
||||||
|
*/
|
||||||
|
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
|
||||||
|
spu.setMarketPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
||||||
|
spu.setMaxPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
|
spu.setMinPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
|
spu.setTotalStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验商品分类是否合法
|
||||||
|
*
|
||||||
|
* @param id 商品分类编号
|
||||||
|
*/
|
||||||
|
private void validateCategory(Long id) {
|
||||||
|
categoryService.validateCategory(id);
|
||||||
|
// 校验层级
|
||||||
|
if (categoryService.getCategoryLevel(id) != 3) {
|
||||||
|
throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteSpu(Long id) {
|
public void deleteSpu(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
validateSpuExists(id);
|
validateSpuExists(id);
|
||||||
@ -126,48 +138,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
// TODO @芋艿:需要再 review 下
|
public ProductSpuDO getSpu(Long id) {
|
||||||
public ProductSpuDetailRespVO getSpuDetail(Long id) {
|
return productSpuMapper.selectById(id);
|
||||||
ProductSpuDO spu = productSpuMapper.selectById(id);
|
|
||||||
ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class);
|
|
||||||
if (null != spu) {
|
|
||||||
List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkusBySpuId(id));
|
|
||||||
respVO.setSkus(skuReqs);
|
|
||||||
// 组合 sku 规格属性
|
|
||||||
if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) {
|
|
||||||
List<ProductSkuRespVO.Property> properties = new ArrayList<>();
|
|
||||||
for (ProductSpuDetailRespVO.Sku productSkuRespVO : skuReqs) {
|
|
||||||
properties.addAll(productSkuRespVO.getProperties());
|
|
||||||
}
|
|
||||||
Map<Long, List<ProductSkuBaseVO.Property>> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId));
|
|
||||||
|
|
||||||
List<ProductPropertyValueRespVO> propertyValueList = productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyMaps.keySet()));
|
|
||||||
List<ProductPropertyRespVO> propertyList = productPropertyService.getPropertyList(new ArrayList<>(propertyMaps.keySet()));
|
|
||||||
// 装载组装过后的属性
|
|
||||||
List<ProductPropertyViewRespVO> productPropertyViews = new ArrayList<>();
|
|
||||||
propertyList.forEach(p -> {
|
|
||||||
ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO();
|
|
||||||
productPropertyViewRespVO.setPropertyId(p.getId());
|
|
||||||
productPropertyViewRespVO.setName(p.getName());
|
|
||||||
List<ProductPropertyViewRespVO.Tuple2> propertyValues = new ArrayList<>();
|
|
||||||
// 转换成map是为了能快速获取
|
|
||||||
Map<Long, ProductPropertyValueRespVO> propertyValueMaps = CollectionUtils.convertMap(propertyValueList, ProductPropertyValueRespVO::getId);
|
|
||||||
propertyMaps.get(p.getId()).forEach(pv -> {
|
|
||||||
ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName());
|
|
||||||
propertyValues.add(tuple2);
|
|
||||||
});
|
|
||||||
productPropertyViewRespVO.setPropertyValues(propertyValues.stream().distinct().collect(Collectors.toList()));
|
|
||||||
productPropertyViews.add(productPropertyViewRespVO);
|
|
||||||
});
|
|
||||||
respVO.setProductPropertyViews(productPropertyViews);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return respVO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProductSpuRespVO getSpu(Long id) {
|
|
||||||
return ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectById(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -181,32 +153,22 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
|
public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
|
||||||
// 库存告警的 SPU 编号的集合
|
// 库存告警的 SPU 编号的集合
|
||||||
Set<Long> alarmStockSpuIds = null;
|
Set<Long> alarmStockSpuIds = null;
|
||||||
if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
|
if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) {
|
||||||
alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkusByAlarmStock(), ProductSkuDO::getSpuId);
|
alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId);
|
||||||
if (CollUtil.isEmpty(alarmStockSpuIds)) {
|
if (CollUtil.isEmpty(alarmStockSpuIds)) {
|
||||||
return PageResult.empty();
|
return PageResult.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 分页查询
|
// 分页查询
|
||||||
return ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds));
|
return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<AppSpuPageRespVO> getSpuPage(AppSpuPageReqVO pageReqVO) {
|
public PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
|
||||||
// TODO 芋艿:貌似实现不太合理
|
return productSpuMapper.selectPage(pageReqVO, status);
|
||||||
PageResult<ProductSpuDO> productSpuDOPageResult = productSpuMapper.selectPage(ProductSpuConvert.INSTANCE.convert(pageReqVO));
|
|
||||||
PageResult<AppSpuPageRespVO> pageResult = new PageResult<>();
|
|
||||||
// TODO @芋艿 这里用convert如何解决
|
|
||||||
List<AppSpuPageRespVO> collect = productSpuDOPageResult.getList()
|
|
||||||
.stream()
|
|
||||||
.map(ProductSpuConvert.INSTANCE::convertAppResp)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
pageResult.setList(collect);
|
|
||||||
pageResult.setTotal(productSpuDOPageResult.getTotal());
|
|
||||||
return pageResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,6 +103,25 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
|
|||||||
assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
|
assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCategoryLevel() {
|
||||||
|
// mock 数据
|
||||||
|
ProductCategoryDO category1 = randomPojo(ProductCategoryDO.class,
|
||||||
|
o -> o.setParentId(ProductCategoryDO.PARENT_ID_NULL));
|
||||||
|
productCategoryMapper.insert(category1);
|
||||||
|
ProductCategoryDO category2 = randomPojo(ProductCategoryDO.class,
|
||||||
|
o -> o.setParentId(category1.getId()));
|
||||||
|
productCategoryMapper.insert(category2);
|
||||||
|
ProductCategoryDO category3 = randomPojo(ProductCategoryDO.class,
|
||||||
|
o -> o.setParentId(category2.getId()));
|
||||||
|
productCategoryMapper.insert(category3);
|
||||||
|
|
||||||
|
// 调用,并断言
|
||||||
|
assertEquals(productCategoryService.getCategoryLevel(category1.getId()), 1);
|
||||||
|
assertEquals(productCategoryService.getCategoryLevel(category2.getId()), 2);
|
||||||
|
assertEquals(productCategoryService.getCategoryLevel(category3.getId()), 3);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetCategoryList() {
|
public void testGetCategoryList() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.sku;
|
package cn.iocoder.yudao.module.product.service.sku;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
|
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
|
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
|
||||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
||||||
@ -13,11 +15,16 @@ import org.springframework.boot.test.mock.mockito.MockBean;
|
|||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
@ -42,6 +49,50 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
|
|||||||
@MockBean
|
@MockBean
|
||||||
private ProductPropertyValueService productPropertyValueService;
|
private ProductPropertyValueService productPropertyValueService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSkuList() {
|
||||||
|
// mock 数据
|
||||||
|
ProductSkuDO sku01 = randomPojo(ProductSkuDO.class, o -> { // 测试更新
|
||||||
|
o.setSpuId(1L);
|
||||||
|
o.setProperties(singletonList(new ProductSkuDO.Property(10L, 20L)));
|
||||||
|
});
|
||||||
|
productSkuMapper.insert(sku01);
|
||||||
|
ProductSkuDO sku02 = randomPojo(ProductSkuDO.class, o -> { // 测试删除
|
||||||
|
o.setSpuId(1L);
|
||||||
|
o.setProperties(singletonList(new ProductSkuDO.Property(10L, 30L)));
|
||||||
|
});
|
||||||
|
productSkuMapper.insert(sku02);
|
||||||
|
// 准备参数
|
||||||
|
Long spuId = 1L;
|
||||||
|
String spuName = "测试商品";
|
||||||
|
List<ProductSkuCreateOrUpdateReqVO> skus = Arrays.asList(
|
||||||
|
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试更新
|
||||||
|
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 20L)));
|
||||||
|
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
}),
|
||||||
|
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试新增
|
||||||
|
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 40L)));
|
||||||
|
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
productSkuService.updateSkuList(spuId, spuName, skus);
|
||||||
|
// 断言
|
||||||
|
List<ProductSkuDO> dbSkus = productSkuMapper.selectListBySpuId(spuId);
|
||||||
|
assertEquals(dbSkus.size(), 2);
|
||||||
|
// 断言更新的
|
||||||
|
assertEquals(dbSkus.get(0).getId(), sku01.getId());
|
||||||
|
assertPojoEquals(dbSkus.get(0), skus.get(0), "properties");
|
||||||
|
assertEquals(skus.get(0).getProperties().size(), 1);
|
||||||
|
assertPojoEquals(dbSkus.get(0).getProperties().get(0), skus.get(0).getProperties().get(0));
|
||||||
|
// 断言新增的
|
||||||
|
assertNotEquals(dbSkus.get(1).getId(), sku02.getId());
|
||||||
|
assertPojoEquals(dbSkus.get(1), skus.get(1), "properties");
|
||||||
|
assertEquals(skus.get(1).getProperties().size(), 1);
|
||||||
|
assertPojoEquals(dbSkus.get(1).getProperties().get(0), skus.get(1).getProperties().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateSkuStock_incrSuccess() {
|
public void testUpdateSkuStock_incrSuccess() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
@ -95,4 +146,26 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
|
|||||||
SKU_STOCK_NOT_ENOUGH);
|
SKU_STOCK_NOT_ENOUGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSku_success() {
|
||||||
|
// mock 数据
|
||||||
|
ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);
|
||||||
|
productSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据
|
||||||
|
// 准备参数
|
||||||
|
Long id = dbSku.getId();
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
productSkuService.deleteSku(id);
|
||||||
|
// 校验数据不存在了
|
||||||
|
assertNull(productSkuMapper.selectById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteSku_notExists() {
|
||||||
|
// 准备参数
|
||||||
|
Long id = 1L;
|
||||||
|
|
||||||
|
// 调用, 并断言异常
|
||||||
|
assertServiceException(() -> productSkuService.deleteSku(id), SKU_NOT_EXISTS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.product.service.sku;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
|
||||||
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
|
|
||||||
// TODO 芋艿:整合到 {@link ProductSkuServiceTest} 中
|
|
||||||
/**
|
|
||||||
* {@link ProductSkuServiceImpl} 的单元测试类
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Import(ProductSkuServiceImpl.class)
|
|
||||||
@Disabled // TODO 芋艿:临时去掉
|
|
||||||
public class SkuServiceImplTest extends BaseDbUnitTest {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ProductSkuServiceImpl ProductSkuService;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ProductSkuMapper ProductSkuMapper;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteSku_success() {
|
|
||||||
// mock 数据
|
|
||||||
ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);
|
|
||||||
ProductSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据
|
|
||||||
// 准备参数
|
|
||||||
Long id = dbSku.getId();
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
ProductSkuService.deleteSku(id);
|
|
||||||
// 校验数据不存在了
|
|
||||||
assertNull(ProductSkuMapper.selectById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDeleteSku_notExists() {
|
|
||||||
// 准备参数
|
|
||||||
Long id = 1L;
|
|
||||||
|
|
||||||
// 调用, 并断言异常
|
|
||||||
assertServiceException(() -> ProductSkuService.deleteSku(id), SKU_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -8,12 +8,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||||
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
||||||
@ -94,9 +94,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
|
ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
|
||||||
|
|
||||||
createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
||||||
createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
// createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
// createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
// createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
||||||
|
|
||||||
assertPojoEquals(createReqVO, productSpuDO);
|
assertPojoEquals(createReqVO, productSpuDO);
|
||||||
|
|
||||||
@ -118,9 +118,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
|
|
||||||
List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = reqVO.getSkus();
|
List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = reqVO.getSkus();
|
||||||
reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
||||||
reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
// reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
// reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
||||||
reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
// reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
||||||
|
|
||||||
// 校验是否更新正确
|
// 校验是否更新正确
|
||||||
ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的
|
ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的
|
||||||
@ -149,60 +149,13 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId()));
|
Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void getSpuDetail() {
|
|
||||||
// 准备spu参数
|
|
||||||
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> {
|
|
||||||
o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
|
|
||||||
});
|
|
||||||
productSpuMapper.insert(createReqVO);
|
|
||||||
|
|
||||||
// 创建两个属性
|
|
||||||
ArrayList<ProductPropertyRespVO> productPropertyRespVOS = Lists.newArrayList(
|
|
||||||
randomPojo(ProductPropertyRespVO.class),
|
|
||||||
randomPojo(ProductPropertyRespVO.class));
|
|
||||||
|
|
||||||
// 所有属性值
|
|
||||||
ArrayList<ProductPropertyValueRespVO> productPropertyValueRespVO = new ArrayList<>();
|
|
||||||
|
|
||||||
// 每个属性创建属性值
|
|
||||||
productPropertyRespVOS.forEach(v -> {
|
|
||||||
ProductPropertyValueRespVO productPropertyValueRespVO1 = randomPojo(ProductPropertyValueRespVO.class, o -> o.setPropertyId(v.getId()));
|
|
||||||
productPropertyValueRespVO.add(productPropertyValueRespVO1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 属性值建立笛卡尔积
|
|
||||||
Map<Long, List<ProductPropertyValueRespVO>> collect = productPropertyValueRespVO.stream().collect(Collectors.groupingBy(ProductPropertyValueRespVO::getPropertyId));
|
|
||||||
List<List<ProductPropertyValueRespVO>> lists = cartesianProduct(Lists.newArrayList(collect.values()));
|
|
||||||
|
|
||||||
// 准备sku参数
|
|
||||||
ArrayList<ProductSkuDO> productSkuDOS = Lists.newArrayList();
|
|
||||||
lists.forEach(pp -> {
|
|
||||||
List<ProductSkuDO.Property> property = pp.stream().map(ppv -> new ProductSkuDO.Property(ppv.getPropertyId(), ppv.getId())).collect(Collectors.toList());
|
|
||||||
ProductSkuDO productSkuDO = randomPojo(ProductSkuDO.class, o -> {
|
|
||||||
o.setProperties(property);
|
|
||||||
});
|
|
||||||
productSkuDOS.add(productSkuDO);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS);
|
|
||||||
Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);
|
|
||||||
Mockito.when(productPropertyService.getPropertyList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId());
|
|
||||||
|
|
||||||
assertPojoEquals(createReqVO, spuDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getSpu() {
|
void getSpu() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
||||||
productSpuMapper.insert(createReqVO);
|
productSpuMapper.insert(createReqVO);
|
||||||
|
|
||||||
ProductSpuRespVO spu = productSpuService.getSpu(createReqVO.getId());
|
ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId());
|
||||||
assertPojoEquals(createReqVO, spu);
|
assertPojoEquals(createReqVO, spu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +176,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
|
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
|
||||||
productSpuPageReqVO.setAlarmStock(true);
|
productSpuPageReqVO.setAlarmStock(true);
|
||||||
|
|
||||||
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
||||||
|
|
||||||
PageResult<Object> result = PageResult.empty();
|
PageResult<Object> result = PageResult.empty();
|
||||||
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
|
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
|
||||||
@ -267,12 +220,12 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
o.setSpuId(createReqVO.getId());
|
o.setSpuId(createReqVO.getId());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Mockito.when(productSkuService.getSkusByAlarmStock()).thenReturn(productSpuDOS);
|
Mockito.when(productSkuService.getSkuListByAlarmStock()).thenReturn(productSpuDOS);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
|
ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
|
||||||
productSpuPageReqVO.setAlarmStock(true);
|
productSpuPageReqVO.setAlarmStock(true);
|
||||||
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
||||||
|
|
||||||
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
|
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds));
|
||||||
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
|
Assertions.assertIterableEquals(result.getList(), spuPage.getList());
|
||||||
@ -324,7 +277,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
|
productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
|
||||||
productSpuPageReqVO.setCategoryId(categoryId);
|
productSpuPageReqVO.setCategoryId(categoryId);
|
||||||
|
|
||||||
PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
||||||
|
|
||||||
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
|
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set<Long>) null));
|
||||||
assertEquals(result, spuPage);
|
assertEquals(result, spuPage);
|
||||||
@ -339,21 +292,21 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|||||||
productSpuMapper.insert(createReqVO);
|
productSpuMapper.insert(createReqVO);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
AppSpuPageReqVO appSpuPageReqVO = new AppSpuPageReqVO();
|
AppProductSpuPageReqVO appSpuPageReqVO = new AppProductSpuPageReqVO();
|
||||||
appSpuPageReqVO.setCategoryId(2L);
|
appSpuPageReqVO.setCategoryId(2L);
|
||||||
|
|
||||||
PageResult<AppSpuPageRespVO> spuPage = productSpuService.getSpuPage(appSpuPageReqVO);
|
// PageResult<AppSpuPageItemRespVO> spuPage = productSpuService.getSpuPage(appSpuPageReqVO);
|
||||||
|
//
|
||||||
PageResult<ProductSpuDO> result = productSpuMapper.selectPage(
|
// PageResult<ProductSpuDO> result = productSpuMapper.selectPage(
|
||||||
ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO));
|
// ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO));
|
||||||
|
//
|
||||||
List<AppSpuPageRespVO> collect = result.getList()
|
// List<AppSpuPageItemRespVO> collect = result.getList()
|
||||||
.stream()
|
// .stream()
|
||||||
.map(ProductSpuConvert.INSTANCE::convertAppResp)
|
// .map(ProductSpuConvert.INSTANCE::convertAppResp)
|
||||||
.collect(Collectors.toList());
|
// .collect(Collectors.toList());
|
||||||
|
//
|
||||||
Assertions.assertIterableEquals(collect, spuPage.getList());
|
// Assertions.assertIterableEquals(collect, spuPage.getList());
|
||||||
assertEquals(spuPage.getTotal(), result.getTotal());
|
// assertEquals(spuPage.getTotal(), result.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `product_sku` (
|
CREATE TABLE IF NOT EXISTS `product_sku` (
|
||||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
`spu_id` bigint NOT NULL COMMENT 'spu编号',
|
`spu_id` bigint NOT NULL COMMENT 'spu编号',
|
||||||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
|
`spu_name` varchar DEFAULT NULL COMMENT '商品 SPU 名字',
|
||||||
`name` varchar DEFAULT NULL COMMENT '商品 SKU 名字',
|
|
||||||
`properties` varchar DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',
|
`properties` varchar DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',
|
||||||
`price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分',
|
`price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分',
|
||||||
`market_price` int DEFAULT NULL COMMENT '市场价',
|
`market_price` int DEFAULT NULL COMMENT '市场价',
|
||||||
@ -52,3 +51,19 @@ CREATE TABLE IF NOT EXISTS `product_spu` (
|
|||||||
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) COMMENT '商品spu';
|
) COMMENT '商品spu';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `product_category` (
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
|
||||||
|
`parent_id` bigint DEFAULT NULL COMMENT '父分类编号',
|
||||||
|
`name` varchar(128) NOT NULL COMMENT '分类名称',
|
||||||
|
`description` varchar(128) NOT NULL COMMENT '分类描述',
|
||||||
|
`pic_url` varchar DEFAULT NULL COMMENT '分类图片',
|
||||||
|
`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
|
||||||
|
`status` bit(1) DEFAULT NULL COMMENT '状态',
|
||||||
|
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
`creator` varchar DEFAULT NULL COMMENT '创建人',
|
||||||
|
`updater` varchar DEFAULT NULL COMMENT '更新人',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) COMMENT '商品分类';
|
||||||
|
@ -45,4 +45,16 @@ public interface ErrorCodeConstants {
|
|||||||
// ========== Price 相关 1003007000 ============
|
// ========== Price 相关 1003007000 ============
|
||||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1003007000, "支付价格计算异常,原因:价格小于等于 0");
|
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1003007000, "支付价格计算异常,原因:价格小于等于 0");
|
||||||
|
|
||||||
|
// ========== 秒杀活动 1003008000 ==========
|
||||||
|
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1003008000, "秒杀活动不存在");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003008002, "存在商品参加了其它秒杀活动");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003008003, "秒杀活动已关闭,不能修改");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1003008004, "秒杀活动未关闭或未结束,不能删除");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003008005, "秒杀活动已关闭,不能重复关闭");
|
||||||
|
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1003008006, "秒杀活动已结束,不能关闭");
|
||||||
|
|
||||||
|
// ========== 秒杀时段 1003009000 ==========
|
||||||
|
ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1003009000, "秒杀时段不存在");
|
||||||
|
ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1003009001, "秒杀时段冲突");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user