Initial commit
This commit is contained in:
56
jy-shop/README.md
Normal file
56
jy-shop/README.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# jy-shop 商城模块
|
||||
|
||||
## 模块说明
|
||||
|
||||
本模块从 mall4j-master 项目中迁移商城相关功能。
|
||||
|
||||
## 需要迁移的Controller
|
||||
|
||||
### 后台管理Controller (从 yami-shop-admin 迁移)
|
||||
|
||||
需要迁移到 `com.ruoyi.jyshop.controller.admin` 包下:
|
||||
|
||||
1. **AreaController** - 区域管理
|
||||
2. **AttributeController** - 属性管理
|
||||
3. **BrandController** - 品牌管理
|
||||
4. **CategoryController** - 分类管理
|
||||
5. **DeliveryController** - 物流公司管理
|
||||
6. **FileController** - 文件上传管理
|
||||
7. **OrderController** - 订单管理
|
||||
8. **PickAddrController** - 自提地址管理
|
||||
9. **ProdCommController** - 商品评论管理
|
||||
10. **ProductController** → **ProdController** - 商品管理(需要重命名)
|
||||
11. **SpecController** - 规格管理
|
||||
12. **TransportController** - 运费模板管理
|
||||
13. **UserAddrController** - 用户地址管理
|
||||
|
||||
### 前端API Controller (从 yami-shop-api 迁移)
|
||||
|
||||
需要迁移到 `com.ruoyi.jyshop.controller.api` 包下:
|
||||
|
||||
1. **AddrController** → **UserAddrApiController** - 用户地址API
|
||||
2. **AreaController** → **AreaApiController** - 区域API
|
||||
3. **CategoryController** → **CategoryApiController** - 分类API
|
||||
4. **DeliveryController** → **DeliveryApiController** - 物流API
|
||||
5. **OrderController** → **OrderApiController** - 订单API
|
||||
6. **MyOrderController** → **MyOrderApiController** - 我的订单API
|
||||
7. **PayController** → **PayApiController** - 支付API
|
||||
8. **ProdCommController** → **ProdCommApiController** - 商品评论API
|
||||
9. **ProdController** → **ProdApiController** - 商品API
|
||||
10. **SkuController** → **SkuApiController** - SKU API
|
||||
|
||||
## 迁移注意事项
|
||||
|
||||
1. **包名修改**:将 `com.yami.shop` 改为 `com.ruoyi.jyshop`
|
||||
2. **依赖处理**:需要迁移相关的Service、Mapper、Domain等类
|
||||
3. **权限注解**:需要适配若依的权限体系
|
||||
4. **响应格式**:需要适配若依的响应格式(AjaxResult)
|
||||
5. **表名映射**:数据库表名从 `tz_` 前缀改为 `shop_` 前缀
|
||||
|
||||
## 数据库表
|
||||
|
||||
所有表的前缀从 `tz_` 改为 `shop_`,详见 `sql/jy-shop.sql`
|
||||
|
||||
## 菜单配置
|
||||
|
||||
菜单SQL已生成,详见 `sql/jy-shop-menu.sql`
|
||||
84
jy-shop/pom.xml
Normal file
84
jy-shop/pom.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<?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>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.8.8</version>
|
||||
</parent>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>jy-shop</artifactId>
|
||||
|
||||
<description>
|
||||
jy shop商城模块
|
||||
</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok 注解处理器 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.5.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Hutool工具类 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.16</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PDF 文本提取(发票识别) -->
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>2.0.29</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 图片 OCR 通过子进程调用本机 tesseract CLI,不再使用 Tess4J JNI -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.apache.hive</groupId>-->
|
||||
<!-- <artifactId>hive-jdbc</artifactId>-->
|
||||
<!-- <version>5.0.1</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 发票图片 OCR 配置(Tesseract 未正确安装时请保持 enabled=false)
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "invoice.ocr")
|
||||
public class InvoiceOcrProperties {
|
||||
|
||||
/** 是否启用图片 OCR(通过子进程调用 tesseract CLI) */
|
||||
private boolean enabled = false;
|
||||
|
||||
/** 可选:TESSDATA_PREFIX,tessdata 的父目录,如 /opt/tesseract 或 C:/Program Files/Tesseract-OCR */
|
||||
private String dataPath;
|
||||
|
||||
/** tesseract 可执行文件路径,Linux 建议 /usr/local/bin/tesseract(需 4.0+) */
|
||||
private String tesseractCmd;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getDataPath() {
|
||||
return dataPath;
|
||||
}
|
||||
|
||||
public void setDataPath(String dataPath) {
|
||||
this.dataPath = dataPath;
|
||||
}
|
||||
|
||||
public String getTesseractCmd() {
|
||||
return tesseractCmd;
|
||||
}
|
||||
|
||||
public void setTesseractCmd(String tesseractCmd) {
|
||||
this.tesseractCmd = tesseractCmd;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.constant;
|
||||
|
||||
/**
|
||||
* 商城 Redis 缓存 key 常量
|
||||
*/
|
||||
public final class ShopCacheConstants {
|
||||
|
||||
/** 待支付订单倒计时 Hash:field=orderNumber, value=过期时间戳(ms) */
|
||||
public static final String ORDER_UNPAY_EXPIRE = "shop:order:unpay";
|
||||
|
||||
/** 倒计时时长:10 分钟(毫秒) */
|
||||
public static final long UNPAY_EXPIRE_MS = 10 * 60 * 1000L;
|
||||
|
||||
private ShopCacheConstants() {}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Area;
|
||||
import com.ruoyi.jyshop.enums.AreaLevelEnum;
|
||||
import com.ruoyi.jyshop.service.IAreaService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 区域管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/area")
|
||||
public class AreaController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IAreaService areaService;
|
||||
|
||||
/**
|
||||
* 分页查询区域列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(Area area, Page<Area> page) {
|
||||
startPage();
|
||||
IPage<Area> areaPage = areaService.page(page, new LambdaQueryWrapper<Area>());
|
||||
return getDataTable(areaPage.getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取区域列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:list')")
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(Area area) {
|
||||
List<Area> areas = areaService.list(new LambdaQueryWrapper<Area>()
|
||||
.like(area.getName() != null, Area::getName, area.getName()));
|
||||
return success(areas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过父级id获取区域列表
|
||||
*/
|
||||
@GetMapping("/listByPid")
|
||||
public AjaxResult listByPid(Long pid) {
|
||||
List<Area> list = areaService.listByPid(pid);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取区域详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
Area area = areaService.getById(id);
|
||||
return success(area);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增区域
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:add')")
|
||||
@Log(title = "区域", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Valid @RequestBody Area area) {
|
||||
if (area.getParentId() != null) {
|
||||
Area parentArea = areaService.getById(area.getParentId());
|
||||
if (parentArea != null) {
|
||||
area.setLevel(parentArea.getLevel() + 1);
|
||||
areaService.removeAreaCacheByParentId(area.getParentId());
|
||||
}
|
||||
}
|
||||
return toAjax(areaService.save(area));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改区域
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:edit')")
|
||||
@Log(title = "区域", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Valid @RequestBody Area area) {
|
||||
Area areaDb = areaService.getById(area.getId());
|
||||
if (areaDb == null) {
|
||||
return error("区域不存在");
|
||||
}
|
||||
// 判断当前省市区级别,如果是1级、2级则不能修改级别,不能修改成别人的下级
|
||||
if (Objects.equals(areaDb.getLevel(), AreaLevelEnum.FIRST_LEVEL.value())
|
||||
&& !Objects.equals(area.getLevel(), AreaLevelEnum.FIRST_LEVEL.value())) {
|
||||
throw new ServiceException("不能改变一级行政地区的级别");
|
||||
}
|
||||
if (Objects.equals(areaDb.getLevel(), AreaLevelEnum.SECOND_LEVEL.value())
|
||||
&& !Objects.equals(area.getLevel(), AreaLevelEnum.SECOND_LEVEL.value())) {
|
||||
throw new ServiceException("不能改变二级行政地区的级别");
|
||||
}
|
||||
hasSameName(area);
|
||||
areaService.removeAreaCacheByParentId(area.getParentId());
|
||||
return toAjax(areaService.updateById(area));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除区域
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:area:remove')")
|
||||
@Log(title = "区域", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable Long id) {
|
||||
Area area = areaService.getById(id);
|
||||
if (area == null) {
|
||||
return error("区域不存在");
|
||||
}
|
||||
areaService.removeById(id);
|
||||
areaService.removeAreaCacheByParentId(area.getParentId());
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有同名区域
|
||||
*/
|
||||
private void hasSameName(Area area) {
|
||||
long count = areaService.count(new LambdaQueryWrapper<Area>()
|
||||
.eq(Area::getParentId, area.getParentId())
|
||||
.eq(Area::getName, area.getName())
|
||||
.ne(Objects.nonNull(area.getId()) && !Objects.equals(area.getId(), 0L),
|
||||
Area::getId, area.getId())
|
||||
);
|
||||
if (count > 0) {
|
||||
throw new ServiceException("该地区已存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.jyshop.domain.ProdProp;
|
||||
import com.ruoyi.jyshop.service.IProdPropService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 参数管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/admin/attribute")
|
||||
public class AttributeController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IProdPropService prodPropService;
|
||||
|
||||
/**
|
||||
* 分页查询参数列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:attribute:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(ProdProp prodProp, Page<ProdProp> page) {
|
||||
startPage();
|
||||
IPage<ProdProp> prodPropPage = prodPropService.pagePropAndValue(prodProp, page);
|
||||
return getDataTable(prodPropPage.getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:attribute:query')")
|
||||
@GetMapping("/info/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
ProdProp prodProp = prodPropService.getById(id);
|
||||
return success(prodProp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增参数
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:attribute:add')")
|
||||
@Log(title = "参数", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Valid @RequestBody ProdProp prodProp) {
|
||||
prodPropService.saveProdPropAndValues(prodProp);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改参数
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:attribute:edit')")
|
||||
@Log(title = "参数", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Valid @RequestBody ProdProp prodProp) {
|
||||
ProdProp dbProdProp = prodPropService.getById(prodProp.getId());
|
||||
if (dbProdProp == null) {
|
||||
return error("参数不存在");
|
||||
}
|
||||
prodPropService.updateProdPropAndValues(prodProp);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除参数
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:attribute:remove')")
|
||||
@Log(title = "参数", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable Long id) {
|
||||
prodPropService.deleteProdPropAndValues(id);
|
||||
return success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Category;
|
||||
import com.ruoyi.jyshop.service.ICategoryService;
|
||||
import com.ruoyi.jyshop.utils.ShopSecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 分类管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/category")
|
||||
public class CategoryController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ICategoryService categoryService;
|
||||
|
||||
/**
|
||||
* 获取菜单页面的表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:category:list')")
|
||||
@GetMapping("/table")
|
||||
public AjaxResult table() {
|
||||
List<Category> categoryMenuList = categoryService.tableCategory(ShopSecurityUtils.getShopId());
|
||||
return success(categoryMenuList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:category:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
Category category = categoryService.getById(id);
|
||||
return success(category);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存分类
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:category:add')")
|
||||
@Log(title = "分类", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody Category category) {
|
||||
category.setShopId(ShopSecurityUtils.getShopId());
|
||||
category.setCreateTime(new Date());
|
||||
Category exist = categoryService.getOne(new LambdaQueryWrapper<Category>()
|
||||
.eq(Category::getName, category.getName())
|
||||
.eq(Category::getShopId, category.getShopId()));
|
||||
if (Objects.nonNull(exist)) {
|
||||
throw new ServiceException("类目名称已存在!");
|
||||
}
|
||||
categoryService.saveCategory(category);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新分类
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:category:edit')")
|
||||
@Log(title = "分类", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody Category category) {
|
||||
category.setShopId(ShopSecurityUtils.getShopId());
|
||||
if (Objects.equals(category.getParentId(), category.getId())) {
|
||||
return error("分类的上级不能是自己本身");
|
||||
}
|
||||
Category exist = categoryService.getOne(new LambdaQueryWrapper<Category>()
|
||||
.eq(Category::getName, category.getName())
|
||||
.eq(Category::getShopId, category.getShopId())
|
||||
.ne(Category::getId, category.getId()));
|
||||
if (exist != null) {
|
||||
throw new ServiceException("类目名称已存在!");
|
||||
}
|
||||
Category categoryDb = categoryService.getById(category.getId());
|
||||
if (categoryDb == null) {
|
||||
return error("分类不存在");
|
||||
}
|
||||
// 如果从下线改成正常,则需要判断上级的状态
|
||||
if (Objects.equals(categoryDb.getStatus(), 0) && Objects.equals(category.getStatus(), 1)
|
||||
&& !Objects.equals(category.getParentId(), 0L)) {
|
||||
Category parentCategory = categoryService.getOne(new LambdaQueryWrapper<Category>()
|
||||
.eq(Category::getId, category.getParentId()));
|
||||
if (Objects.isNull(parentCategory) || Objects.equals(parentCategory.getStatus(), 0)) {
|
||||
// 修改失败,上级分类不存在或者不为正常状态
|
||||
throw new ServiceException("修改失败,上级分类不存在或者不为正常状态");
|
||||
}
|
||||
}
|
||||
categoryService.updateCategory(category);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:category:remove')")
|
||||
@Log(title = "分类", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable("id") Long id) {
|
||||
if (categoryService.count(new LambdaQueryWrapper<Category>()
|
||||
.eq(Category::getParentId, id)) > 0) {
|
||||
return error("请删除子分类,再删除该分类");
|
||||
}
|
||||
categoryService.deleteCategory(id);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有分类(二级及以下)
|
||||
*/
|
||||
@GetMapping("/listCategory")
|
||||
public AjaxResult listCategory() {
|
||||
List<Category> list = categoryService.list(new LambdaQueryWrapper<Category>()
|
||||
.le(Category::getLevel, 2)
|
||||
.eq(Category::getShopId, ShopSecurityUtils.getShopId())
|
||||
.orderByAsc(Category::getSeq));
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有产品分类(树形结构)
|
||||
*/
|
||||
@GetMapping("/listProdCategory")
|
||||
public AjaxResult listProdCategory() {
|
||||
List<Category> categories = categoryService.treeSelect(ShopSecurityUtils.getShopId(), 2);
|
||||
return success(categories);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.jyshop.domain.Delivery;
|
||||
import com.ruoyi.jyshop.service.IDeliveryService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 物流公司管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/admin/delivery")
|
||||
public class DeliveryController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IDeliveryService deliveryService;
|
||||
|
||||
/**
|
||||
* 获取物流公司列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list() {
|
||||
List<Delivery> list = deliveryService.list();
|
||||
return success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.framework.config.ServerConfig;
|
||||
import com.ruoyi.jyshop.service.IAttachFileService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文件上传Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/admin/file")
|
||||
public class FileController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IAttachFileService attachFileService;
|
||||
|
||||
@Autowired
|
||||
private ServerConfig serverConfig;
|
||||
|
||||
/**
|
||||
* Element UI文件上传
|
||||
*/
|
||||
@PostMapping("/upload/element")
|
||||
public AjaxResult uploadElementFile(@RequestParam("file") MultipartFile file) throws IOException {
|
||||
if (file.isEmpty()) {
|
||||
return success();
|
||||
}
|
||||
String fileName = attachFileService.uploadFile(file);
|
||||
String url = serverConfig.getUrl() + fileName;
|
||||
AjaxResult ajax = success();
|
||||
ajax.put("url", url);
|
||||
ajax.put("fileName", fileName);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
/**
|
||||
* TinyMCE编辑器图片上传
|
||||
*/
|
||||
@PostMapping("/upload/tinymceEditor")
|
||||
public AjaxResult uploadTinymceEditorImages(@RequestParam("editorFile") MultipartFile editorFile) throws IOException {
|
||||
String fileName = attachFileService.uploadFile(editorFile);
|
||||
String url = serverConfig.getUrl() + fileName;
|
||||
return success(url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import cn.hutool.poi.excel.ExcelWriter;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.domain.OrderItem;
|
||||
import com.ruoyi.jyshop.domain.OrderAddr;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderLog;
|
||||
import com.ruoyi.jyshop.enums.OrderStatus;
|
||||
import com.ruoyi.jyshop.service.IOrderItemService;
|
||||
import com.ruoyi.jyshop.service.IOrderService;
|
||||
import com.ruoyi.jyshop.service.IOrderAddrService;
|
||||
import com.ruoyi.jyshop.service.IShopOrderLogService;
|
||||
import com.ruoyi.jyshop.utils.ShopSecurityUtils;
|
||||
import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.jyshop.vo.DeliveryOrderParam;
|
||||
import com.ruoyi.jyshop.vo.OrderParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 订单管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/shop/order")
|
||||
public class OrderController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IOrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private IOrderItemService orderItemService;
|
||||
|
||||
@Autowired
|
||||
private IOrderAddrService orderAddrService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IShopOrderLogService shopOrderLogService;
|
||||
|
||||
/**
|
||||
* 分页查询订单列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo page(OrderParam orderParam, Page<Order> page) {
|
||||
// 从请求参数中获取分页信息,设置到 MyBatis-Plus 的 Page,否则分页始终为第 1 页
|
||||
PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
IPage<Order> orderPage = orderService.pageOrdersDetailByOrderParam(page, orderParam);
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.SUCCESS);
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(orderPage.getRecords());
|
||||
dataTable.setTotal(orderPage.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:query')")
|
||||
@GetMapping("/orderInfo/{orderNumber}")
|
||||
public AjaxResult getInfo(@PathVariable("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限获取该订单信息");
|
||||
}
|
||||
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
|
||||
order.setOrderItems(orderItems);
|
||||
OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
|
||||
order.setOrderAddr(orderAddr);
|
||||
|
||||
if (shopOrderLogService != null) {
|
||||
List<ShopOrderLog> orderLogs = shopOrderLogService.list(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ShopOrderLog>()
|
||||
.eq(ShopOrderLog::getOrderNo, orderNumber)
|
||||
.orderByDesc(ShopOrderLog::getCreateTime));
|
||||
order.setOrderLogs(orderLogs);
|
||||
}
|
||||
return success(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发货
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:delivery')")
|
||||
@Log(title = "订单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/delivery")
|
||||
public AjaxResult delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(deliveryOrderParam.getOrderNumber());
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限修改该订单信息");
|
||||
}
|
||||
|
||||
String shippingType = deliveryOrderParam.getDvyType();
|
||||
if ("快递".equals(shippingType)) {
|
||||
if (deliveryOrderParam.getDvyId() == null) {
|
||||
return error("请选择快递公司");
|
||||
}
|
||||
if (deliveryOrderParam.getDvyFlowId() == null || deliveryOrderParam.getDvyFlowId().trim().isEmpty()) {
|
||||
return error("请输入物流单号");
|
||||
}
|
||||
}
|
||||
|
||||
Order orderParam = new Order();
|
||||
orderParam.setId(order.getId());
|
||||
// 录入/修改物流后,订单状态进入待收货
|
||||
orderParam.setStatus(30);
|
||||
orderParam.setUserId(order.getUserId());
|
||||
orderParam.setUpdateTime(new Date());
|
||||
if ("快递".equals(shippingType)) {
|
||||
// 物流公司、物流单号不再回写到 shop_order,而是写入 shop_order_log
|
||||
}
|
||||
|
||||
orderService.delivery(orderParam);
|
||||
|
||||
// 订单日志:发货(待收货),记录物流公司、物流单号
|
||||
if (shopOrderLogService != null) {
|
||||
String logisticsCompany = null;
|
||||
String logisticsNo = null;
|
||||
if ("快递".equals(shippingType) && deliveryOrderParam.getDvyId() != null) {
|
||||
logisticsCompany = DictUtils.getDictLabel("express_company", String.valueOf(deliveryOrderParam.getDvyId()));
|
||||
logisticsNo = deliveryOrderParam.getDvyFlowId();
|
||||
}
|
||||
String operatorId = SecurityUtils.getUserId() != null ? String.valueOf(SecurityUtils.getUserId()) : null;
|
||||
String operatorName = SecurityUtils.getUsername();
|
||||
shopOrderLogService.addLog(deliveryOrderParam.getOrderNumber(), order.getId(), 30, null,
|
||||
logisticsCompany, logisticsNo, operatorId, operatorName);
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货:待收货(30) -> 已收货(31)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:edit')")
|
||||
@Log(title = "订单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/receipt")
|
||||
public AjaxResult receipt(@RequestParam("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限操作该订单信息");
|
||||
}
|
||||
boolean ok = orderService.confirmReceiptByOrderNumber(orderNumber);
|
||||
return ok ? success() : error("确认收货失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 待发货订单退款(关闭订单)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:edit')")
|
||||
@Log(title = "订单退款", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/refund/{orderNumber}")
|
||||
public AjaxResult refund(@PathVariable("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限操作该订单");
|
||||
}
|
||||
orderService.refund(orderNumber);
|
||||
// 订单日志:已取消(管理端关闭订单/退款)
|
||||
if (shopOrderLogService != null) {
|
||||
String operatorId = SecurityUtils.getUserId() != null ? String.valueOf(SecurityUtils.getUserId()) : null;
|
||||
shopOrderLogService.addLog(orderNumber, order.getId(), 4, null, null, null, operatorId, SecurityUtils.getUsername());
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意退货退款:退款退货(61) -> 同意退货(62)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:edit')")
|
||||
@Log(title = "订单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/agreeReturnRefund")
|
||||
public AjaxResult agreeReturnRefund(@RequestParam("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限操作该订单信息");
|
||||
}
|
||||
try {
|
||||
orderService.agreeReturnRefund(orderNumber);
|
||||
return success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收到退货:退货中(63) -> 已退货(64)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:edit')")
|
||||
@Log(title = "订单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/confirmReturnReceipt")
|
||||
public AjaxResult confirmReturnReceipt(@RequestParam("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限操作该订单信息");
|
||||
}
|
||||
try {
|
||||
orderService.confirmMerchantReturnReceived(orderNumber);
|
||||
return success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退货在途物流(用于后台查看退货轨迹)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:query')")
|
||||
@GetMapping("/returnLogistics/{orderNumber}")
|
||||
public AjaxResult returnLogistics(@PathVariable("orderNumber") String orderNumber) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!ObjectUtil.equal(shopId, order.getShopId())) {
|
||||
throw new ServiceException("您没有权限获取该订单信息");
|
||||
}
|
||||
if (shopOrderLogService == null) {
|
||||
return success(null);
|
||||
}
|
||||
ShopOrderLog lg = shopOrderLogService.findLatestReturnLogisticsLog(orderNumber);
|
||||
if (lg == null) {
|
||||
return success(null);
|
||||
}
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("orderNumber", orderNumber);
|
||||
data.put("logisticsCompany", lg.getLogisticsCompany());
|
||||
data.put("logisticsNo", lg.getLogisticsNo());
|
||||
data.put("createTime", lg.getCreateTime());
|
||||
return success(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打印待发货的订单表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:export')")
|
||||
@Log(title = "订单", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/waitingConsignmentExcel")
|
||||
public void waitingConsignmentExcel(Order order,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
|
||||
String consignmentName,
|
||||
String consignmentMobile,
|
||||
String consignmentAddr,
|
||||
HttpServletResponse response) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
order.setShopId(shopId);
|
||||
order.setStatus(OrderStatus.PADYED.value());
|
||||
List<Order> orders = orderService.listOrdersDetailByOrder(order, startTime, endTime);
|
||||
|
||||
// 通过工具类创建writer
|
||||
ExcelWriter writer = ExcelUtil.getBigWriter();
|
||||
Sheet sheet = writer.getSheet();
|
||||
sheet.setColumnWidth(0, 20 * 256);
|
||||
sheet.setColumnWidth(1, 20 * 256);
|
||||
sheet.setColumnWidth(2, 20 * 256);
|
||||
sheet.setColumnWidth(3, 60 * 256);
|
||||
sheet.setColumnWidth(4, 60 * 256);
|
||||
sheet.setColumnWidth(7, 60 * 256);
|
||||
sheet.setColumnWidth(8, 60 * 256);
|
||||
sheet.setColumnWidth(9, 60 * 256);
|
||||
|
||||
// 待发货
|
||||
String[] header = {"订单编号", "收件人", "手机", "收货地址", "商品名称", "数量", "发件人姓名", "发件人手机号", "发货地址", "备注"};
|
||||
writer.merge(header.length - 1, "发货信息整理");
|
||||
writer.writeRow(Arrays.asList(header));
|
||||
|
||||
int row = 1;
|
||||
for (Order dbOrder : orders) {
|
||||
OrderAddr addr = dbOrder.getOrderAddr();
|
||||
if (addr == null) {
|
||||
continue;
|
||||
}
|
||||
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
|
||||
List<OrderItem> orderItems = dbOrder.getOrderItems();
|
||||
if (orderItems == null) {
|
||||
continue;
|
||||
}
|
||||
for (OrderItem orderItem : orderItems) {
|
||||
row++;
|
||||
int col = 0;
|
||||
writer.writeCellValue(col++, row, dbOrder.getOrderNumber());
|
||||
writer.writeCellValue(col++, row, addr.getReceiver());
|
||||
writer.writeCellValue(col++, row, addr.getMobile());
|
||||
writer.writeCellValue(col++, row, addrInfo);
|
||||
writer.writeCellValue(col++, row, orderItem.getProdName());
|
||||
writer.writeCellValue(col++, row, orderItem.getQuantity());
|
||||
writer.writeCellValue(col++, row, consignmentName);
|
||||
writer.writeCellValue(col++, row, consignmentMobile);
|
||||
writer.writeCellValue(col++, row, consignmentAddr);
|
||||
writer.writeCellValue(col++, row, dbOrder.getRemarks());
|
||||
}
|
||||
}
|
||||
writeExcel(response, writer, "待发货订单.xls");
|
||||
}
|
||||
|
||||
/**
|
||||
* 已销售订单导出
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:order:export')")
|
||||
@Log(title = "订单", businessType = BusinessType.EXPORT)
|
||||
@GetMapping("/soldExcel")
|
||||
public void soldExcel(Order order,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
|
||||
HttpServletResponse response) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
order.setShopId(shopId);
|
||||
order.setStatus(OrderStatus.PADYED.value());
|
||||
List<Order> orders = orderService.listOrdersDetailByOrder(order, startTime, endTime);
|
||||
|
||||
// 通过工具类创建writer
|
||||
ExcelWriter writer = ExcelUtil.getBigWriter();
|
||||
String[] header = {"订单编号", "下单时间", "收件人", "手机", "收货地址", "商品名称", "数量", "订单应付", "订单运费", "订单实付"};
|
||||
Sheet sheet = writer.getSheet();
|
||||
sheet.setColumnWidth(0, 20 * 256);
|
||||
sheet.setColumnWidth(1, 20 * 256);
|
||||
sheet.setColumnWidth(3, 20 * 256);
|
||||
sheet.setColumnWidth(4, 60 * 256);
|
||||
sheet.setColumnWidth(5, 60 * 256);
|
||||
|
||||
writer.merge(header.length - 1, "销售信息整理");
|
||||
writer.writeRow(Arrays.asList(header));
|
||||
|
||||
int row = 1;
|
||||
for (Order dbOrder : orders) {
|
||||
OrderAddr addr = dbOrder.getOrderAddr();
|
||||
if (addr == null) {
|
||||
continue;
|
||||
}
|
||||
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
|
||||
List<OrderItem> orderItems = dbOrder.getOrderItems();
|
||||
if (orderItems == null || orderItems.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
int firstRow = row + 1;
|
||||
int lastRow = row + orderItems.size();
|
||||
int col = -1;
|
||||
// 订单编号
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getOrderNumber());
|
||||
// 下单时间
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getCreateTime());
|
||||
// 收件人
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getReceiver());
|
||||
// 手机
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addr.getMobile());
|
||||
// 收货地址
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, addrInfo);
|
||||
int prodNameCol = ++col;
|
||||
int prodCountCol = ++col;
|
||||
for (OrderItem orderItem : orderItems) {
|
||||
row++;
|
||||
// 商品名称
|
||||
writer.writeCellValue(prodNameCol, row, orderItem.getProdName());
|
||||
// 数量
|
||||
writer.writeCellValue(prodCountCol, row, orderItem.getQuantity());
|
||||
}
|
||||
// 订单应付
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getTotalAmount());
|
||||
// 订单运费
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getShippingFee());
|
||||
// 订单实付
|
||||
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getActualTotalAmount());
|
||||
}
|
||||
writeExcel(response, writer, "已销售订单.xls");
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果需要合并的话,就合并
|
||||
*/
|
||||
private void mergeIfNeed(ExcelWriter writer, int firstRow, int lastRow, int firstColumn, int lastColumn, Object content) {
|
||||
if (content instanceof Date) {
|
||||
content = DateUtil.format((Date) content, DatePattern.NORM_DATETIME_PATTERN);
|
||||
}
|
||||
if (lastRow - firstRow > 0 || lastColumn - firstColumn > 0) {
|
||||
writer.merge(firstRow, lastRow, firstColumn, lastColumn, content, false);
|
||||
} else {
|
||||
writer.writeCellValue(firstColumn, firstRow, content);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeExcel(HttpServletResponse response, ExcelWriter writer, String fileName) {
|
||||
// response为HttpServletResponse对象
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
// 设置文件名
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
|
||||
|
||||
ServletOutputStream servletOutputStream = null;
|
||||
try {
|
||||
servletOutputStream = response.getOutputStream();
|
||||
writer.flush(servletOutputStream);
|
||||
servletOutputStream.flush();
|
||||
} catch (IOException e) {
|
||||
log.error("写出Excel错误:", e);
|
||||
} finally {
|
||||
IoUtil.close(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.PickAddr;
|
||||
import com.ruoyi.jyshop.service.IPickAddrService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 自提地址管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/pickAddr")
|
||||
public class PickAddrController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IPickAddrService pickAddrService;
|
||||
|
||||
/**
|
||||
* 分页查询自提地址列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:pickAddr:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(PickAddr pickAddr, Page<PickAddr> page) {
|
||||
startPage();
|
||||
IPage<PickAddr> pickAddrs = pickAddrService.page(page, new LambdaQueryWrapper<PickAddr>()
|
||||
.like(StrUtil.isNotBlank(pickAddr.getAddrName()), PickAddr::getAddrName, pickAddr.getAddrName())
|
||||
.orderByDesc(PickAddr::getAddrId));
|
||||
return getDataTable(pickAddrs.getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自提地址详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:pickAddr:query')")
|
||||
@GetMapping("/info/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
PickAddr pickAddr = pickAddrService.getById(id);
|
||||
return success(pickAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增自提地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:pickAddr:add')")
|
||||
@Log(title = "自提地址", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Valid @RequestBody PickAddr pickAddr) {
|
||||
// 使用适配工具类获取shopId
|
||||
pickAddr.setShopId(com.ruoyi.jyshop.utils.ShopSecurityUtils.getShopId());
|
||||
return toAjax(pickAddrService.save(pickAddr));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改自提地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:pickAddr:edit')")
|
||||
@Log(title = "自提地址", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Valid @RequestBody PickAddr pickAddr) {
|
||||
PickAddr dbPickAddr = pickAddrService.getById(pickAddr.getAddrId());
|
||||
if (dbPickAddr == null) {
|
||||
return error("自提地址不存在");
|
||||
}
|
||||
// 权限检查
|
||||
if (!Objects.equals(dbPickAddr.getShopId(), com.ruoyi.jyshop.utils.ShopSecurityUtils.getShopId())) {
|
||||
throw new ServiceException("无权修改该自提地址");
|
||||
}
|
||||
return toAjax(pickAddrService.updateById(pickAddr));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除自提地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:pickAddr:remove')")
|
||||
@Log(title = "自提地址", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping
|
||||
public AjaxResult remove(@RequestBody Long[] ids) {
|
||||
return toAjax(pickAddrService.removeByIds(Arrays.asList(ids)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Product;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
import com.ruoyi.jyshop.service.IBasketService;
|
||||
import com.ruoyi.jyshop.service.IProdTagService;
|
||||
import com.ruoyi.jyshop.service.IProdSkuService;
|
||||
import com.ruoyi.jyshop.service.IProductService;
|
||||
import com.ruoyi.jyshop.utils.ShopSecurityUtils;
|
||||
import com.ruoyi.jyshop.vo.ProductParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 商品管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/prod")
|
||||
public class ProdController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IProductService productService;
|
||||
|
||||
@Autowired
|
||||
private IProdSkuService prodSkuService;
|
||||
|
||||
@Autowired
|
||||
private IProdTagService prodTagService;
|
||||
|
||||
@Autowired
|
||||
private IBasketService basketService;
|
||||
|
||||
/**
|
||||
* 分页查询商品列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo page(ProductParam product, Page<Product> page) {
|
||||
product.setName(StrUtil.isNotBlank(product.getName()) ? product.getName().trim() : product.getName());
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
// 从请求参数中获取分页信息,设置到MyBatis-Plus的Page对象
|
||||
com.ruoyi.common.core.page.PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
// 不使用startPage(),因为MyBatis-Plus会自动处理分页,避免重复LIMIT
|
||||
IPage<Product> products = productService.page(page,
|
||||
new LambdaQueryWrapper<Product>()
|
||||
.like(StrUtil.isNotBlank(product.getName()), Product::getName, product.getName())
|
||||
.eq(Product::getShopId, shopId)
|
||||
.eq(product.getStatus() != null, Product::getStatus, product.getStatus())
|
||||
.orderByDesc(Product::getUpdateTime));
|
||||
// 使用IPage对象构建TableDataInfo,包含总数信息
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.SUCCESS);
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(products.getRecords());
|
||||
dataTable.setTotal(products.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:query')")
|
||||
@GetMapping("/{prodId}")
|
||||
public AjaxResult getInfo(@PathVariable("prodId") Long prodId) {
|
||||
Product prod = productService.getProductByProdId(prodId);
|
||||
if (prod == null) {
|
||||
return error("商品不存在");
|
||||
}
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
if (!Objects.equals(prod.getShopId(), shopId)) {
|
||||
throw new ServiceException("没有权限获取该商品规格信息");
|
||||
}
|
||||
List<ProdSku> skuList = prodSkuService.listByProdId(prodId);
|
||||
prod.setSkuList(skuList);
|
||||
|
||||
// 获取分组标签
|
||||
List<Long> listTagId = prodTagService.listTagIdByProdId(prodId);
|
||||
prod.setTagList(listTagId);
|
||||
return success(prod);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增商品
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:add')")
|
||||
@Log(title = "商品", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Valid @RequestBody ProductParam productParam) {
|
||||
checkParam(productParam);
|
||||
|
||||
Product product = new Product();
|
||||
BeanUtil.copyProperties(productParam, product);
|
||||
product.setSkuList(productParam.getSkuList());
|
||||
product.setShippingType(productParam.getDeliveryModeVo() != null ? JSON.toJSONString(productParam.getDeliveryModeVo()) : null);
|
||||
product.setShopId(ShopSecurityUtils.getShopId());
|
||||
product.setUpdateTime(new Date());
|
||||
product.setCreateTime(new Date());
|
||||
productService.saveProduct(product);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改商品
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:edit')")
|
||||
@Log(title = "商品", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Valid @RequestBody ProductParam productParam) {
|
||||
checkParam(productParam);
|
||||
Product dbProduct = productService.getProductByProdId(productParam.getId());
|
||||
if (dbProduct == null) {
|
||||
return error("商品不存在");
|
||||
}
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
if (!Objects.equals(dbProduct.getShopId(), shopId)) {
|
||||
return error("无法修改非本店铺商品信息");
|
||||
}
|
||||
|
||||
List<ProdSku> dbSkus = prodSkuService.listByProdId(dbProduct.getId());
|
||||
|
||||
Product product = new Product();
|
||||
BeanUtil.copyProperties(productParam, product);
|
||||
// 覆盖 SKU 列表与分组标签,保证不修改规格时也能正确回写
|
||||
product.setSkuList(productParam.getSkuList());
|
||||
product.setTagList(productParam.getTagList());
|
||||
product.setShippingType(productParam.getDeliveryModeVo() != null ? JSON.toJSONString(productParam.getDeliveryModeVo()) : null);
|
||||
product.setUpdateTime(new Date());
|
||||
|
||||
dbProduct.setSkuList(dbSkus);
|
||||
productService.updateProduct(product, dbProduct);
|
||||
|
||||
// List<String> userIds = basketService.listUserIdByProdId(product.getId());
|
||||
// for (String userId : userIds) {
|
||||
// basketService.removeShopCartItemsCacheByUserId(userId);
|
||||
// }
|
||||
// for (ProdSku sku : dbSkus) {
|
||||
// prodSkuService.removeSkuCacheBySkuId(sku.getId(), sku.getProdId());
|
||||
// }
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品(请求体为 ID 数组)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:remove')")
|
||||
@Log(title = "商品", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping
|
||||
public AjaxResult remove(@RequestBody Long[] prodIds) {
|
||||
for (Long prodId : prodIds) {
|
||||
delete(prodId);
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个商品(路径参数,与前端 delProduct(prodId) 调用方式一致)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:remove')")
|
||||
@Log(title = "商品", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{prodId}")
|
||||
public AjaxResult removeById(@PathVariable("prodId") Long prodId) {
|
||||
delete(prodId);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个商品
|
||||
*/
|
||||
private AjaxResult delete(Long prodId) {
|
||||
Product dbProduct = productService.getProductByProdId(prodId);
|
||||
if (dbProduct == null) {
|
||||
throw new ServiceException("商品不存在");
|
||||
}
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
if (!Objects.equals(dbProduct.getShopId(), shopId)) {
|
||||
throw new ServiceException("无法获取非本店铺商品信息");
|
||||
}
|
||||
List<ProdSku> dbSkus = prodSkuService.listByProdId(dbProduct.getId());
|
||||
// 删除商品
|
||||
productService.removeProductByProdId(prodId);
|
||||
|
||||
for (ProdSku sku : dbSkus) {
|
||||
prodSkuService.removeSkuCacheBySkuId(sku.getId(), sku.getProdId());
|
||||
}
|
||||
|
||||
// List<String> userIds = basketService.listUserIdByProdId(prodId);
|
||||
// for (String userId : userIds) {
|
||||
// basketService.removeShopCartItemsCacheByUserId(userId);
|
||||
// }
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品状态
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:prod:edit')")
|
||||
@Log(title = "商品", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/prodStatus")
|
||||
public AjaxResult changeStatus(@RequestParam Long prodId, @RequestParam Integer prodStatus) {
|
||||
Product product = new Product();
|
||||
product.setId(prodId);
|
||||
product.setStatus(prodStatus);
|
||||
productService.updateById(product);
|
||||
productService.removeProductCacheByProdId(prodId);
|
||||
// List<String> userIds = basketService.listUserIdByProdId(prodId);
|
||||
// for (String userId : userIds) {
|
||||
// basketService.removeShopCartItemsCacheByUserId(userId);
|
||||
// }
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验参数
|
||||
*/
|
||||
private void checkParam(ProductParam productParam) {
|
||||
// 产品分组验证:如果tagList为空,设置默认值(临时方案)
|
||||
// TODO: 后续需要添加产品分组选择功能,或创建默认分组
|
||||
if (CollUtil.isEmpty(productParam.getTagList())) {
|
||||
// 临时方案:设置默认分组ID为1,如果数据库中没有,需要先创建
|
||||
// 或者可以改为允许为空,但需要修改业务逻辑
|
||||
productParam.setTagList(java.util.Arrays.asList(1L));
|
||||
}
|
||||
|
||||
Product.DeliveryModeVO deliveryMode = productParam.getDeliveryModeVo();
|
||||
boolean hasDeliverMode = deliveryMode != null
|
||||
&& (deliveryMode.getHasShopDelivery() != null && deliveryMode.getHasShopDelivery()
|
||||
|| deliveryMode.getHasUserPickUp() != null && deliveryMode.getHasUserPickUp());
|
||||
if (!hasDeliverMode) {
|
||||
throw new ServiceException("请选择配送方式");
|
||||
}
|
||||
List<ProdSku> skuList = productParam.getSkuList();
|
||||
if (CollUtil.isEmpty(skuList)) {
|
||||
throw new ServiceException("请至少添加一种商品规格");
|
||||
}
|
||||
boolean isAllUnUse = true;
|
||||
for (ProdSku sku : skuList) {
|
||||
if (sku.getStatus() != null && sku.getStatus() == 1) {
|
||||
isAllUnUse = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isAllUnUse) {
|
||||
throw new ServiceException("至少要启用一种商品规格");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplate;
|
||||
import com.ruoyi.jyshop.service.IShippingTemplateService;
|
||||
import com.ruoyi.jyshop.utils.ShopSecurityUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板管理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/shipping-template")
|
||||
public class ShippingTemplateController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IShippingTemplateService shippingTemplateService;
|
||||
|
||||
/**
|
||||
* 分页查询运费模板列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:shippingTemplate:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(ShippingTemplate query, Page<ShippingTemplate> page) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
com.ruoyi.common.core.page.PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
IPage<ShippingTemplate> result = shippingTemplateService.page(page,
|
||||
new LambdaQueryWrapper<ShippingTemplate>()
|
||||
.eq(ShippingTemplate::getShopId, shopId)
|
||||
.like(StringUtils.isNotBlank(query.getName()), ShippingTemplate::getName, query.getName()));
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.SUCCESS);
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(result.getRecords());
|
||||
dataTable.setTotal(result.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运费模板详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:shippingTemplate:query')")
|
||||
@GetMapping("/info/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id) {
|
||||
ShippingTemplate template = shippingTemplateService.getTemplateAndAllItems(id);
|
||||
return success(template);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增运费模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:shippingTemplate:add')")
|
||||
@Log(title = "运费模板", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody ShippingTemplate template) {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
template.setShopId(shopId);
|
||||
template.setCreateTime(new Date());
|
||||
shippingTemplateService.insertTemplateAndRules(template);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改运费模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:shippingTemplate:edit')")
|
||||
@Log(title = "运费模板", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody ShippingTemplate template) {
|
||||
shippingTemplateService.updateTemplateAndRules(template);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除运费模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:shippingTemplate:remove')")
|
||||
@Log(title = "运费模板", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping
|
||||
public AjaxResult remove(@RequestBody Long[] ids) {
|
||||
shippingTemplateService.deleteTemplateAndRules(ids);
|
||||
for (Long id : ids) {
|
||||
shippingTemplateService.removeTemplateCache(id);
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运费模板列表(不分页)
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list() {
|
||||
Long shopId = ShopSecurityUtils.getShopId();
|
||||
List<ShippingTemplate> list = shippingTemplateService.list(
|
||||
new LambdaQueryWrapper<ShippingTemplate>().eq(ShippingTemplate::getShopId, shopId));
|
||||
return success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.jyshop.domain.ShopInvoiceBasic;
|
||||
import com.ruoyi.jyshop.service.IShopInvoiceBasicService;
|
||||
import com.ruoyi.jyshop.vo.InvoiceManualParam;
|
||||
import com.ruoyi.jyshop.vo.InvoiceRecognizeResult;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 发票重复校验
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/invoice")
|
||||
public class ShopInvoiceController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IShopInvoiceBasicService shopInvoiceBasicService;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('shop:invoice:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(ShopInvoiceBasic query, Page<ShopInvoiceBasic> page) {
|
||||
PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
com.baomidou.mybatisplus.core.metadata.IPage<ShopInvoiceBasic> result =
|
||||
shopInvoiceBasicService.pageList(page, query);
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.SUCCESS);
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(result.getRecords());
|
||||
dataTable.setTotal(result.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('shop:invoice:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getInfo(@PathVariable Long id) {
|
||||
return success(shopInvoiceBasicService.getById(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('shop:invoice:upload')")
|
||||
@Log(title = "发票识别入库", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/upload")
|
||||
public AjaxResult upload(@RequestParam("file") MultipartFile file) throws IOException {
|
||||
InvoiceRecognizeResult result = shopInvoiceBasicService.recognizeAndSave(
|
||||
file, SecurityUtils.getUsername());
|
||||
AjaxResult ajax = success(result);
|
||||
ajax.put("duplicate", result.isDuplicate());
|
||||
ajax.put("saved", result.isSaved());
|
||||
ajax.put("message", result.getMessage());
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('shop:invoice:upload')")
|
||||
@Log(title = "发票手动录入", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/manual")
|
||||
public AjaxResult manual(@RequestBody InvoiceManualParam param) {
|
||||
ShopInvoiceBasic saved = shopInvoiceBasicService.saveManualInvoiceNumber(
|
||||
param.getInvoiceNumber(), SecurityUtils.getUsername());
|
||||
return success(saved);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('shop:invoice:remove')")
|
||||
@Log(title = "发票", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids) {
|
||||
return toAjax(shopInvoiceBasicService.removeByIds(Arrays.asList(ids)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.jyshop.domain.ProdProp;
|
||||
import com.ruoyi.jyshop.domain.ProdPropDtl;
|
||||
import com.ruoyi.jyshop.service.IProdPropService;
|
||||
import com.ruoyi.jyshop.service.IProdPropDtlService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 规格管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/spec")
|
||||
public class SpecController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IProdPropService prodPropService;
|
||||
|
||||
@Autowired
|
||||
private IProdPropDtlService prodPropDtlService;
|
||||
|
||||
/**
|
||||
* 分页查询规格列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:spec:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(ProdProp prodProp, Page<ProdProp> page) {
|
||||
startPage();
|
||||
IPage<ProdProp> list = prodPropService.pagePropAndValue(prodProp, page);
|
||||
return getDataTable(list.getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的规格
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list() {
|
||||
List<ProdProp> list = prodPropService.list();
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取规格详情(含规格值列表)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:spec:query')")
|
||||
@GetMapping("/{id}")
|
||||
public AjaxResult getInfo(@PathVariable Long id) {
|
||||
ProdProp prop = prodPropService.getById(id);
|
||||
if (prop == null) {
|
||||
return error("规格不存在");
|
||||
}
|
||||
List<ProdPropDtl> dtls = prodPropDtlService.list(new LambdaQueryWrapper<ProdPropDtl>()
|
||||
.eq(ProdPropDtl::getPropId, id));
|
||||
prop.setProdPropDtls(dtls);
|
||||
return success(prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据规格id获取规格值
|
||||
*/
|
||||
@GetMapping("/listSpecValue/{specId}")
|
||||
public AjaxResult listSpecValue(@PathVariable("specId") Long specId) {
|
||||
List<ProdPropDtl> list = prodPropDtlService.list(new LambdaQueryWrapper<ProdPropDtl>()
|
||||
.eq(ProdPropDtl::getPropId, specId));
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增规格
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:spec:add')")
|
||||
@Log(title = "规格", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@Valid @RequestBody ProdProp prodProp) {
|
||||
prodPropService.saveProdPropAndValues(prodProp);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改规格
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:spec:edit')")
|
||||
@Log(title = "规格", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@Valid @RequestBody ProdProp prodProp) {
|
||||
ProdProp dbProdProp = prodPropService.getById(prodProp.getId());
|
||||
if (dbProdProp == null) {
|
||||
return error("规格不存在");
|
||||
}
|
||||
prodPropService.updateProdPropAndValues(prodProp);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除规格
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:spec:remove')")
|
||||
@Log(title = "规格", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{id}")
|
||||
public AjaxResult remove(@PathVariable Long id) {
|
||||
prodPropService.deleteProdPropAndValues(id);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据获取规格值最大的自增id
|
||||
*/
|
||||
@GetMapping("/listSpecMaxValueId")
|
||||
public AjaxResult listSpecMaxValueId() {
|
||||
ProdPropDtl dtl = prodPropDtlService.getOne(new LambdaQueryWrapper<ProdPropDtl>()
|
||||
.orderByDesc(ProdPropDtl::getId).last("limit 1"));
|
||||
return success(Objects.isNull(dtl) ? 0L : dtl.getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.ruoyi.jyshop.controller.admin;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.jyshop.domain.UserAddr;
|
||||
import com.ruoyi.jyshop.service.IUserAddrService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 用户地址管理Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/user/addr")
|
||||
public class UserAddrController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IUserAddrService userAddrService;
|
||||
|
||||
/**
|
||||
* 分页查询用户地址列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:userAddr:list')")
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(Page<UserAddr> page, UserAddr userAddr) {
|
||||
startPage();
|
||||
IPage<UserAddr> userAddrPage = userAddrService.page(page, new LambdaQueryWrapper<UserAddr>());
|
||||
return getDataTable(userAddrPage.getRecords());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户地址详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:userAddr:query')")
|
||||
@GetMapping("/info/{addrId}")
|
||||
public AjaxResult getInfo(@PathVariable("addrId") Long addrId) {
|
||||
UserAddr userAddr = userAddrService.getById(addrId);
|
||||
return success(userAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:userAddr:add')")
|
||||
@Log(title = "用户地址", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody @Valid UserAddr userAddr) {
|
||||
return toAjax(userAddrService.save(userAddr));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:userAddr:edit')")
|
||||
@Log(title = "用户地址", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody @Valid UserAddr userAddr) {
|
||||
return toAjax(userAddrService.updateById(userAddr));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户地址
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('shop:userAddr:remove')")
|
||||
@Log(title = "用户地址", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{addrId}")
|
||||
public AjaxResult remove(@PathVariable Long addrId) {
|
||||
return toAjax(userAddrService.removeById(addrId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.jyshop.domain.Area;
|
||||
import com.ruoyi.jyshop.service.IAreaService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 省市区API Controller(店铺前台用,无需 admin 权限)
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/area")
|
||||
public class AreaApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IAreaService areaService;
|
||||
|
||||
/**
|
||||
* 获取全部地区列表(用于收货地址等页面的省市区级联)
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list() {
|
||||
List<Area> areas = areaService.list();
|
||||
return success(areas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据省市区的pid获取地址信息
|
||||
*/
|
||||
@GetMapping("/listByPid")
|
||||
public AjaxResult listByPid(@RequestParam(value = "pid", defaultValue = "0") Long pid) {
|
||||
List<Area> list = areaService.listByPid(pid);
|
||||
return success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.jyshop.domain.Category;
|
||||
import com.ruoyi.jyshop.service.ICategoryService;
|
||||
import com.ruoyi.jyshop.vo.CategoryDto;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/category")
|
||||
public class CategoryApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ICategoryService categoryService;
|
||||
|
||||
/**
|
||||
* 分类信息列表
|
||||
*/
|
||||
@GetMapping("/categoryInfo")
|
||||
public AjaxResult categoryInfo(@RequestParam(value = "parentId", defaultValue = "0") Long parentId) {
|
||||
List<Category> categories = categoryService.listByParentId(parentId);
|
||||
List<CategoryDto> categoryDtos = BeanUtil.copyToList(categories, CategoryDto.class);
|
||||
return success(categoryDtos);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Delivery;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderLog;
|
||||
import com.ruoyi.jyshop.service.IDeliveryService;
|
||||
import com.ruoyi.jyshop.service.IShopOrderLogService;
|
||||
import com.ruoyi.jyshop.vo.DeliveryDto;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 查看物流API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/delivery")
|
||||
public class DeliveryApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IDeliveryService deliveryService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IShopOrderLogService shopOrderLogService;
|
||||
|
||||
/**
|
||||
* 查看物流
|
||||
*/
|
||||
@GetMapping("/check")
|
||||
public AjaxResult checkDelivery(@RequestParam("orderNumber") String orderNumber) {
|
||||
if (shopOrderLogService == null) {
|
||||
throw new ServiceException("订单日志服务未启用");
|
||||
}
|
||||
|
||||
// 从 shop_order_log 查最新物流记录(取最新一条且物流单号非空)
|
||||
LambdaQueryWrapper<ShopOrderLog> qw = new LambdaQueryWrapper<ShopOrderLog>()
|
||||
.eq(ShopOrderLog::getOrderNo, orderNumber)
|
||||
.isNotNull(ShopOrderLog::getLogisticsNo)
|
||||
.orderByDesc(ShopOrderLog::getCreateTime)
|
||||
.last("limit 1");
|
||||
ShopOrderLog log = shopOrderLogService.getOne(qw);
|
||||
if (log == null || log.getLogisticsNo() == null || log.getLogisticsNo().trim().isEmpty()) {
|
||||
throw new ServiceException("未查到物流信息");
|
||||
}
|
||||
|
||||
// logisticsCompany 写入的是 express_company 的 dict label,这里按 dvyName 匹配
|
||||
Delivery delivery = deliveryService.getOne(
|
||||
new LambdaQueryWrapper<Delivery>()
|
||||
.eq(Delivery::getDvyName, log.getLogisticsCompany())
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
if (delivery == null) {
|
||||
throw new ServiceException("物流公司信息不存在");
|
||||
}
|
||||
|
||||
String url = delivery.getQueryUrl().replace("{dvyFlowId}", log.getLogisticsNo());
|
||||
String deliveryJson = HttpUtil.get(url);
|
||||
|
||||
DeliveryDto deliveryDto = JSON.parseObject(deliveryJson, DeliveryDto.class);
|
||||
deliveryDto.setDvyFlowId(log.getLogisticsNo());
|
||||
deliveryDto.setCompanyHomeUrl(delivery.getCompanyHomeUrl());
|
||||
deliveryDto.setCompanyName(delivery.getDvyName());
|
||||
return success(deliveryDto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.jyshop.service.IInviteCodeService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 邀请码 API(C 端校验)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/inviteCode")
|
||||
public class InviteCodeApiController extends BaseController {
|
||||
|
||||
private static final String CONFIG_INVITE_ENABLED = "sys.invitecode.enabled";
|
||||
|
||||
@Autowired
|
||||
private IInviteCodeService inviteCodeService;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
|
||||
/** 是否启用邀请码功能 */
|
||||
private boolean isInviteCodeEnabled() {
|
||||
String v = configService.selectConfigByKey(CONFIG_INVITE_ENABLED);
|
||||
return Convert.toBool(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邀请码功能是否开启
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
public AjaxResult config() {
|
||||
boolean enabled = isInviteCodeEnabled();
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("enabled", enabled);
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验邀请码是否可用于下单
|
||||
* 0-初始可用,1-已下单(未支付),2-已支付;不存在返回 -1
|
||||
*/
|
||||
@GetMapping("/validate")
|
||||
public AjaxResult validate(@RequestParam("code") String code) {
|
||||
if (!isInviteCodeEnabled()) {
|
||||
return error("系统未开启邀请码功能");
|
||||
}
|
||||
if (code == null || code.trim().isEmpty()) {
|
||||
return error("请输入邀请码");
|
||||
}
|
||||
Integer status = inviteCodeService.validateForUse(code.trim());
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("status", status == null ? -1 : status);
|
||||
return success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.domain.OrderItem;
|
||||
import com.ruoyi.jyshop.domain.OrderAddr;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderLog;
|
||||
import com.ruoyi.jyshop.service.IOrderItemService;
|
||||
import com.ruoyi.jyshop.service.IOrderService;
|
||||
import com.ruoyi.jyshop.service.IOrderAddrService;
|
||||
import com.ruoyi.jyshop.service.IOrderUnpayCountdownService;
|
||||
import com.ruoyi.jyshop.service.IShopOrderLogService;
|
||||
import com.ruoyi.jyshop.utils.ApiSecurityUtils;
|
||||
import com.ruoyi.jyshop.vo.OrderDetailDto;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import com.ruoyi.jyshop.vo.UserReturnLogisticsParam;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ruoyi.jyshop.enums.OrderStatus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 我的订单API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/myOrder")
|
||||
public class MyOrderApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IOrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private IOrderAddrService orderAddrService;
|
||||
|
||||
@Autowired
|
||||
private IOrderItemService orderItemService;
|
||||
|
||||
@Autowired
|
||||
private IOrderUnpayCountdownService orderUnpayCountdownService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IShopOrderLogService shopOrderLogService;
|
||||
|
||||
/**
|
||||
* 订单详情信息
|
||||
*/
|
||||
@GetMapping("/orderDetail")
|
||||
public AjaxResult orderDetail(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
throw new ServiceException("该订单不存在");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), userId)) {
|
||||
throw new ServiceException("你没有权限获取该订单信息");
|
||||
}
|
||||
|
||||
OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
|
||||
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
|
||||
|
||||
// 构建返回DTO
|
||||
OrderDetailDto detailDto = new OrderDetailDto();
|
||||
detailDto.setOrder(order);
|
||||
detailDto.setOrderAddr(orderAddr);
|
||||
detailDto.setOrderItems(orderItems);
|
||||
|
||||
return success(detailDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户某个订单的最新物流记录(从 shop_order_log 表中获取)
|
||||
*/
|
||||
@GetMapping("/logisticsInfo")
|
||||
public AjaxResult logisticsInfo(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), userId)) {
|
||||
return error("无权查看该订单物流信息");
|
||||
}
|
||||
// 无日志服务或无物流记录时返回 200 + data=null,避免前端全局错误提示,由前端提示「未查到物流信息」
|
||||
if (shopOrderLogService == null) {
|
||||
return success(null);
|
||||
}
|
||||
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ShopOrderLog> qw =
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ShopOrderLog>()
|
||||
.eq(ShopOrderLog::getOrderNo, orderNumber)
|
||||
.isNotNull(ShopOrderLog::getLogisticsNo)
|
||||
.orderByDesc(ShopOrderLog::getCreateTime)
|
||||
.last("limit 1");
|
||||
ShopOrderLog log = shopOrderLogService.getOne(qw);
|
||||
if (log == null) {
|
||||
return success(null);
|
||||
}
|
||||
java.util.Map<String, Object> data = new java.util.HashMap<>();
|
||||
data.put("orderNumber", orderNumber);
|
||||
data.put("logisticsCompany", log.getLogisticsCompany());
|
||||
data.put("logisticsNo", log.getLogisticsNo());
|
||||
data.put("createTime", log.getCreateTime());
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询我的订单
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo page(@RequestParam(value = "status", required = false) Integer status,
|
||||
Page<Order> page) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
// 返回空列表而不是null,避免NullPointerException
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.OK.value());
|
||||
dataTable.setMsg("用户未登录");
|
||||
dataTable.setRows(new java.util.ArrayList<>());
|
||||
dataTable.setTotal(0L);
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
// 从请求参数中获取分页信息,设置到MyBatis-Plus的Page对象
|
||||
com.ruoyi.common.core.page.PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
|
||||
// 构建查询条件
|
||||
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
|
||||
.eq(Order::getUserId, userId)
|
||||
.eq(status != null, Order::getStatus, status)
|
||||
.orderByDesc(Order::getCreateTime);
|
||||
|
||||
// 执行分页查询
|
||||
IPage<Order> orderPage = orderService.page(page, queryWrapper);
|
||||
|
||||
// 为每个订单填充订单项和地址信息
|
||||
List<Order> orders = orderPage.getRecords();
|
||||
for (Order order : orders) {
|
||||
// 获取订单项
|
||||
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(order.getOrderNumber());
|
||||
order.setOrderItems(orderItems);
|
||||
|
||||
// 获取订单地址
|
||||
if (order.getOrderAddrId() != null) {
|
||||
OrderAddr orderAddr = orderAddrService.getById(order.getOrderAddrId());
|
||||
order.setOrderAddr(orderAddr);
|
||||
}
|
||||
// 待付款列表:返回 10 分钟倒计时过期时间戳(毫秒)
|
||||
if (status != null && status == 0) {
|
||||
Long expireAt = orderUnpayCountdownService.getExpireAt(order.getOrderNumber());
|
||||
order.setUnpayExpireAt(expireAt);
|
||||
}
|
||||
}
|
||||
|
||||
// 使用IPage对象构建TableDataInfo,包含总数信息
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.OK.value());
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(orders);
|
||||
dataTable.setTotal(orderPage.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单(由调用方传入取消后的订单状态码)
|
||||
*/
|
||||
@PutMapping("/cancel")
|
||||
public AjaxResult cancel(@RequestParam("orderNumber") String orderNumber,
|
||||
@RequestParam("cancelStatus") Integer cancelStatus) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), userId)) {
|
||||
return error("无权操作该订单");
|
||||
}
|
||||
if (!OrderStatus.UNPAY.value().equals(order.getStatus())) {
|
||||
return error("仅待付款订单可取消");
|
||||
}
|
||||
String operatorName = ApiSecurityUtils.getUserName();
|
||||
boolean ok = orderService.cancelByOrderNumber(orderNumber, userId, operatorName, cancelStatus);
|
||||
return ok ? success() : error("取消失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货(待收货订单更新为状态3-完成)
|
||||
*/
|
||||
@PutMapping("/receipt")
|
||||
public AjaxResult receipt(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), userId)) {
|
||||
return error("无权操作该订单");
|
||||
}
|
||||
// 兼容新状态码:30(待收货),以及历史旧落库值:2(待收货)
|
||||
if (order.getStatus() == null || (order.getStatus() != 30 && !OrderStatus.CONSIGNMENT.value().equals(order.getStatus()))) {
|
||||
return error("仅待收货订单可确认收货");
|
||||
}
|
||||
boolean ok = orderService.confirmReceiptByOrderNumber(orderNumber);
|
||||
return ok ? success() : error("确认收货失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户发起仅退款:待发货(2) -> 仅退款(60)
|
||||
*/
|
||||
@PutMapping("/refundApply")
|
||||
public AjaxResult refundApply(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
try {
|
||||
orderService.applyRefundRequestByUser(orderNumber, userId, ApiSecurityUtils.getUserName());
|
||||
return success("已提交退款申请,请等待商家处理");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户申请退货退款:已收货(31) -> 退款退货(61)
|
||||
*/
|
||||
@PutMapping("/returnRefundApply")
|
||||
public AjaxResult returnRefundApply(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
try {
|
||||
orderService.applyReturnRefundByUser(orderNumber, userId, ApiSecurityUtils.getUserName());
|
||||
return success("已提交退货退款申请,请等待商家审核");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户录入退货物流:同意退货(62) -> 退货中(63)
|
||||
*/
|
||||
@PutMapping("/returnLogistics")
|
||||
public AjaxResult returnLogistics(@RequestBody UserReturnLogisticsParam param) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
if (param == null || param.getOrderNumber() == null || param.getOrderNumber().trim().isEmpty()) {
|
||||
return error("订单号不能为空");
|
||||
}
|
||||
try {
|
||||
orderService.submitUserReturnLogistics(param.getOrderNumber().trim(), userId, ApiSecurityUtils.getUserName(),
|
||||
param.getLogisticsCompany(), param.getLogisticsNo());
|
||||
return success("退货物流已提交");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前用户订单的退货在途物流(状态 63 日志)
|
||||
*/
|
||||
@GetMapping("/returnLogisticsInfo")
|
||||
public AjaxResult returnLogisticsInfo(@RequestParam("orderNumber") String orderNumber) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单不存在");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), userId)) {
|
||||
return error("无权查看该订单");
|
||||
}
|
||||
if (shopOrderLogService == null) {
|
||||
return success(null);
|
||||
}
|
||||
ShopOrderLog lg = shopOrderLogService.findLatestReturnLogisticsLog(orderNumber);
|
||||
if (lg == null) {
|
||||
return success(null);
|
||||
}
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("orderNumber", orderNumber);
|
||||
data.put("logisticsCompany", lg.getLogisticsCompany());
|
||||
data.put("logisticsNo", lg.getLogisticsNo());
|
||||
data.put("createTime", lg.getCreateTime());
|
||||
return success(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.domain.OrderItem;
|
||||
import com.ruoyi.jyshop.domain.Product;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
import com.ruoyi.jyshop.domain.UserAddr;
|
||||
import com.ruoyi.jyshop.domain.OrderAddr;
|
||||
import com.ruoyi.jyshop.service.IOrderItemService;
|
||||
import com.ruoyi.jyshop.service.IOrderService;
|
||||
import com.ruoyi.jyshop.service.IProductService;
|
||||
import com.ruoyi.jyshop.service.IProdSkuService;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.jyshop.service.IShippingTemplateService;
|
||||
import com.ruoyi.jyshop.service.IOrderAddrService;
|
||||
import com.ruoyi.jyshop.service.IUserAddrService;
|
||||
import com.ruoyi.jyshop.service.IInviteCodeService;
|
||||
import com.ruoyi.jyshop.service.IShopOrderLogService;
|
||||
import com.ruoyi.jyshop.service.IOrderUnpayCountdownService;
|
||||
import com.ruoyi.jyshop.utils.ApiSecurityUtils;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.jyshop.utils.OrderCacheUtil;
|
||||
import com.ruoyi.jyshop.vo.OrderConfirmDto;
|
||||
import com.ruoyi.jyshop.vo.OrderItemDto;
|
||||
import com.ruoyi.jyshop.vo.OrderItemParam;
|
||||
import com.ruoyi.jyshop.vo.OrderNumbersDto;
|
||||
import com.ruoyi.jyshop.vo.OrderParam;
|
||||
import com.ruoyi.jyshop.vo.OrderShopParam;
|
||||
import com.ruoyi.jyshop.vo.SubmitOrderParam;
|
||||
import com.ruoyi.jyshop.vo.UserAddrDto;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 订单API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/order")
|
||||
public class OrderApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IUserAddrService userAddrService;
|
||||
|
||||
@Autowired
|
||||
private IProductService productService;
|
||||
|
||||
@Autowired
|
||||
private IProdSkuService prodSkuService;
|
||||
|
||||
@Autowired
|
||||
private IOrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private IOrderItemService orderItemService;
|
||||
|
||||
@Autowired
|
||||
private IOrderAddrService orderAddrService;
|
||||
|
||||
@Autowired
|
||||
private IShippingTemplateService shippingTemplateService;
|
||||
|
||||
@Autowired
|
||||
private IInviteCodeService inviteCodeService;
|
||||
|
||||
@Autowired
|
||||
private IOrderUnpayCountdownService orderUnpayCountdownService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IShopOrderLogService shopOrderLogService;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
|
||||
private static final String CONFIG_INVITE_ENABLED = "sys.invitecode.enabled";
|
||||
|
||||
/** 是否启用邀请码功能 */
|
||||
private boolean isInviteCodeEnabled() {
|
||||
String v = configService.selectConfigByKey(CONFIG_INVITE_ENABLED);
|
||||
return Convert.toBool(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据运费模板和用户选择的地址返回运费
|
||||
*
|
||||
* @param templateId 运费模板ID(必填)
|
||||
* @param addrId 用户收货地址ID(必填,0 表示默认地址)
|
||||
* @param totalAmount 订单金额(可选,用于包邮条件,默认 0)
|
||||
* @param totalCount 件数(可选,默认 1)
|
||||
* @param totalWeight 总重量 kg(可选,按重量计费时使用,默认 0)
|
||||
* @param totalVolume 总体积 m³(可选,按体积计费时使用,默认 0)
|
||||
*/
|
||||
@GetMapping("/transfee")
|
||||
public AjaxResult transfee(
|
||||
@RequestParam String templateId,
|
||||
@RequestParam(required = false) String addrId,
|
||||
@RequestParam(required = false) Double totalAmount,
|
||||
@RequestParam(required = false) Integer totalCount,
|
||||
@RequestParam(required = false) Double totalWeight,
|
||||
@RequestParam(required = false) Double totalVolume) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
if (templateId == null || templateId.trim().isEmpty()) {
|
||||
return error("运费模板不能为空");
|
||||
}
|
||||
Long templateIdLong;
|
||||
try {
|
||||
templateIdLong = Long.parseLong(templateId.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
return error("运费模板ID格式无效");
|
||||
}
|
||||
if (templateIdLong <= 0) {
|
||||
return error("运费模板不能为空");
|
||||
}
|
||||
Long addrIdLong = 0L;
|
||||
if (addrId != null && !addrId.trim().isEmpty()) {
|
||||
try {
|
||||
addrIdLong = Long.parseLong(addrId.trim());
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrIdLong, userId);
|
||||
List<Long> userAreaIds = new ArrayList<>();
|
||||
if (userAddr != null) {
|
||||
if (userAddr.getAreaId() != null) userAreaIds.add(userAddr.getAreaId());
|
||||
if (userAddr.getCityId() != null && !userAreaIds.contains(userAddr.getCityId())) userAreaIds.add(userAddr.getCityId());
|
||||
if (userAddr.getProvinceId() != null && !userAreaIds.contains(userAddr.getProvinceId())) userAreaIds.add(userAddr.getProvinceId());
|
||||
}
|
||||
double amount = totalAmount != null ? totalAmount : 0.0;
|
||||
int count = totalCount != null && totalCount > 0 ? totalCount : 1;
|
||||
double weight = totalWeight != null ? totalWeight : 0.0;
|
||||
double volume = totalVolume != null ? totalVolume : 0.0;
|
||||
double transfee = shippingTemplateService.calculateTransfee(templateIdLong, userAreaIds, amount, count, weight, volume);
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("transfee", transfee);
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认订单(生成订单信息)
|
||||
*/
|
||||
@PostMapping("/confirm")
|
||||
public AjaxResult confirm(@RequestBody OrderParam orderParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
// 1. 获取用户地址(必须用当前传入的地址 id 查库,运费按该地址的省/市/区计算)
|
||||
Long addrId = orderParam.getId() != null ? orderParam.getId() : 0L;
|
||||
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
|
||||
|
||||
// 2. 获取订单商品项
|
||||
List<OrderItemDto> orderItems = new ArrayList<>();
|
||||
if (orderParam.getOrderItem() != null) {
|
||||
// 立即购买
|
||||
OrderItemParam orderItemParam = orderParam.getOrderItem();
|
||||
OrderItemDto orderItemDto = buildOrderItem(orderItemParam);
|
||||
if (orderItemDto != null) {
|
||||
orderItems.add(orderItemDto);
|
||||
}
|
||||
} else if (!CollectionUtils.isEmpty(orderParam.getBasketIds())) {
|
||||
// 购物车购买(暂不支持,返回错误)
|
||||
return error("购物车功能暂未实现");
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(orderItems)) {
|
||||
return error("请选择您需要的商品");
|
||||
}
|
||||
|
||||
// 3. 计算订单金额与按运费模板汇总(用于计算运费)[0]=金额 [1]=件数 [2]=重量(kg) [3]=体积(m³)
|
||||
double total = 0.0;
|
||||
int totalCount = 0;
|
||||
Map<Long, double[]> transportToAmountCount = new LinkedHashMap<>();
|
||||
|
||||
for (OrderItemDto orderItem : orderItems) {
|
||||
totalCount += orderItem.getQuantity();
|
||||
double itemTotal = orderItem.getUnitPrice() * orderItem.getQuantity();
|
||||
orderItem.setTotalAmount(itemTotal);
|
||||
total += itemTotal;
|
||||
|
||||
Product product = productService.getProductByProdId(orderItem.getProdId());
|
||||
Long templateId = product != null ? product.getShippingTemplateId() : null;
|
||||
if (templateId == null && product != null && product.getShopId() != null) {
|
||||
templateId = shippingTemplateService.getFirstTemplateIdByShopId(product.getShopId());
|
||||
}
|
||||
if (templateId != null) {
|
||||
transportToAmountCount.computeIfAbsent(templateId, k -> new double[]{0.0, 0.0, 0.0, 0.0});
|
||||
double[] arr = transportToAmountCount.get(templateId);
|
||||
arr[0] += itemTotal;
|
||||
arr[1] += orderItem.getQuantity();
|
||||
double w = orderItem.getWeight() != null ? orderItem.getWeight() : 0.0;
|
||||
double v = orderItem.getVolume() != null ? orderItem.getVolume() : 0.0;
|
||||
arr[2] += w * orderItem.getQuantity();
|
||||
arr[3] += v * orderItem.getQuantity();
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 根据运费模板计算运费(必须用当前选中地址的区/市/区ID参与模板匹配)
|
||||
List<Long> userAreaIds = new ArrayList<>();
|
||||
if (userAddr != null) {
|
||||
if (userAddr.getAreaId() != null) userAreaIds.add(userAddr.getAreaId());
|
||||
if (userAddr.getCityId() != null && !userAreaIds.contains(userAddr.getCityId())) userAreaIds.add(userAddr.getCityId());
|
||||
if (userAddr.getProvinceId() != null && !userAreaIds.contains(userAddr.getProvinceId())) userAreaIds.add(userAddr.getProvinceId());
|
||||
}
|
||||
double transfee = 0.0;
|
||||
for (Map.Entry<Long, double[]> e : transportToAmountCount.entrySet()) {
|
||||
double amount = e.getValue()[0];
|
||||
int count = (int) e.getValue()[1];
|
||||
double weight = e.getValue()[2];
|
||||
double volume = e.getValue()[3];
|
||||
transfee += shippingTemplateService.calculateTransfee(e.getKey(), userAreaIds, amount, count, weight, volume);
|
||||
}
|
||||
|
||||
// 5. 构建返回结果
|
||||
OrderConfirmDto confirmDto = new OrderConfirmDto();
|
||||
confirmDto.setOrderItems(orderItems);
|
||||
confirmDto.setTotal(total);
|
||||
confirmDto.setActualTotal(total + transfee);
|
||||
confirmDto.setTotalCount(totalCount);
|
||||
confirmDto.setTransfee(transfee);
|
||||
confirmDto.setShopReduce(0.0);
|
||||
// 供前端调用 /order/transfee 用:有模板取第一个,无则用店铺默认模板
|
||||
Long firstTemplateId = null;
|
||||
if (!transportToAmountCount.isEmpty()) {
|
||||
firstTemplateId = transportToAmountCount.keySet().iterator().next();
|
||||
} else if (!orderItems.isEmpty()) {
|
||||
firstTemplateId = shippingTemplateService.getFirstTemplateIdByShopId(1L);
|
||||
}
|
||||
if (firstTemplateId != null) {
|
||||
confirmDto.setShippingTemplateId(firstTemplateId);
|
||||
}
|
||||
|
||||
// 设置用户地址
|
||||
if (userAddr != null) {
|
||||
UserAddrDto userAddrDto = new UserAddrDto();
|
||||
BeanUtils.copyProperties(userAddr, userAddrDto);
|
||||
confirmDto.setUserAddr(userAddrDto);
|
||||
}
|
||||
|
||||
// 保存到缓存
|
||||
OrderCacheUtil.put(userId, confirmDto);
|
||||
|
||||
return success(confirmDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建订单项
|
||||
*/
|
||||
private OrderItemDto buildOrderItem(OrderItemParam orderItemParam) {
|
||||
Long prodId = orderItemParam.getProdId();
|
||||
if (prodId == null) {
|
||||
throw new ServiceException("商品ID不能为空");
|
||||
}
|
||||
// 获取商品信息
|
||||
Product product = productService.getProductByProdId(prodId);
|
||||
if (product == null) {
|
||||
throw new ServiceException("商品不存在(商品ID:" + prodId + "),请确认商品是否已下架或删除");
|
||||
}
|
||||
if (product.getStatus() != 1) {
|
||||
throw new ServiceException("商品[" + product.getName() + "]已下架");
|
||||
}
|
||||
|
||||
// sku_id 必须有值,由商品页传递
|
||||
Long skuId = orderItemParam.getSkuId();
|
||||
if (skuId == null) {
|
||||
throw new ServiceException("请选择商品规格");
|
||||
}
|
||||
ProdSku sku = prodSkuService.getProdSkuBySkuId(skuId);
|
||||
if (sku == null) {
|
||||
throw new ServiceException("商品规格不存在");
|
||||
}
|
||||
if (sku.getStatus() != 1) {
|
||||
throw new ServiceException("商品规格[" + sku.getName() + "]已下架");
|
||||
}
|
||||
if (sku.getLatestInventory() == null || sku.getLatestInventory() < orderItemParam.getQuantity()) {
|
||||
throw new ServiceException("商品[" + (sku.getProdName() != null ? sku.getProdName() : product.getName()) + "]库存不足");
|
||||
}
|
||||
|
||||
OrderItemDto orderItemDto = new OrderItemDto();
|
||||
orderItemDto.setProdId(product.getId());
|
||||
orderItemDto.setProdName(product.getName());
|
||||
orderItemDto.setQuantity(orderItemParam.getQuantity());
|
||||
orderItemDto.setSkuId(sku.getId());
|
||||
orderItemDto.setSkuName(sku.getName() != null ? sku.getName() : "默认规格");
|
||||
orderItemDto.setUnitPrice(sku.getLatestPrice());
|
||||
orderItemDto.setOriPrice(sku.getRegularPrice());
|
||||
orderItemDto.setPic(sku.getPic() != null ? sku.getPic() : product.getMainPic());
|
||||
orderItemDto.setWeight(sku.getWeight());
|
||||
orderItemDto.setVolume(sku.getVolume());
|
||||
|
||||
return orderItemDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交订单
|
||||
*/
|
||||
@PostMapping("/submit")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult submit(@RequestBody SubmitOrderParam submitOrderParam,
|
||||
@RequestParam(value = "addrId", required = false) String addrIdParam,
|
||||
@RequestParam(value = "addId", required = false) String addIdParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
// 1. 从缓存获取订单确认信息(仅用于订单项、金额、运费,不用于地址)
|
||||
OrderConfirmDto confirmDto = OrderCacheUtil.get(userId);
|
||||
if (confirmDto == null) {
|
||||
return error("订单已过期,请重新下单");
|
||||
}
|
||||
|
||||
// 2. 地址ID 用字符串接收再解析,避免 Long/数字在传输或反序列化时后几位被截断
|
||||
String addrIdStr = null;
|
||||
if (submitOrderParam.getAddrId() != null && !submitOrderParam.getAddrId().trim().isEmpty()) {
|
||||
addrIdStr = submitOrderParam.getAddrId().trim();
|
||||
} else if (submitOrderParam.getAddId() != null && !submitOrderParam.getAddId().trim().isEmpty()) {
|
||||
addrIdStr = submitOrderParam.getAddId().trim();
|
||||
} else if (addrIdParam != null && !addrIdParam.trim().isEmpty()) {
|
||||
addrIdStr = addrIdParam.trim();
|
||||
} else if (addIdParam != null && !addIdParam.trim().isEmpty()) {
|
||||
addrIdStr = addIdParam.trim();
|
||||
}
|
||||
if (addrIdStr == null) {
|
||||
return error("请选择收货地址");
|
||||
}
|
||||
Long addrId;
|
||||
try {
|
||||
addrId = Long.parseLong(addrIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
return error("收货地址ID格式无效");
|
||||
}
|
||||
if (addrId <= 0) {
|
||||
return error("请选择收货地址");
|
||||
}
|
||||
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
|
||||
if (userAddr == null) {
|
||||
return error("收货地址无效或不存在");
|
||||
}
|
||||
|
||||
// 2.1 邀请码功能开启时,若带了邀请码,校验状态必须为初始(0)才允许提交
|
||||
String inviteCode = submitOrderParam.getInviteCode();
|
||||
boolean inviteEnabled = isInviteCodeEnabled();
|
||||
if (inviteEnabled && inviteCode != null && !inviteCode.trim().isEmpty()) {
|
||||
Integer inviteStatus = inviteCodeService.validateForUse(inviteCode.trim());
|
||||
if (inviteStatus == null) {
|
||||
return error("邀请码不存在");
|
||||
}
|
||||
if (inviteStatus == 1) {
|
||||
return error("您的邀请码已经被未支付的订单使用了");
|
||||
}
|
||||
if (inviteStatus == 2) {
|
||||
return error("您的邀请码已经被使用了");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 验证订单项
|
||||
if (CollectionUtils.isEmpty(confirmDto.getOrderItems())) {
|
||||
return error("订单商品不能为空");
|
||||
}
|
||||
|
||||
// 4. 保存订单地址(使用提交表单传入的 addrId 查出的地址,不从缓存取)
|
||||
OrderAddr orderAddr = new OrderAddr();
|
||||
BeanUtils.copyProperties(userAddr, orderAddr);
|
||||
orderAddr.setId(null);
|
||||
orderAddr.setUserAddrId(userAddr.getId());
|
||||
orderAddr.setUserId(userId);
|
||||
orderAddr.setCreateTime(new Date());
|
||||
orderAddrService.save(orderAddr);
|
||||
Long orderAddrId = orderAddr.getId();
|
||||
|
||||
// 5. 获取订单备注
|
||||
String remarks = "";
|
||||
if (!CollectionUtils.isEmpty(submitOrderParam.getOrderShopParam())) {
|
||||
OrderShopParam orderShopParam = submitOrderParam.getOrderShopParam().get(0);
|
||||
remarks = orderShopParam != null ? orderShopParam.getRemarks() : "";
|
||||
}
|
||||
|
||||
// 6. 创建订单
|
||||
Date now = new Date();
|
||||
String orderNumber = generateOrderNumber();
|
||||
Long shopId = 1L; // 默认店铺ID
|
||||
|
||||
// 构建订单商品名称
|
||||
StringBuilder orderProdName = new StringBuilder();
|
||||
List<OrderItem> orderItems = new ArrayList<>();
|
||||
int totalCount = 0;
|
||||
double total = 0.0;
|
||||
double transfee = confirmDto.getTransfee() != null ? confirmDto.getTransfee() : 0.0;
|
||||
|
||||
for (OrderItemDto orderItemDto : confirmDto.getOrderItems()) {
|
||||
// 验证商品
|
||||
Product product = productService.getProductByProdId(orderItemDto.getProdId());
|
||||
if (product == null || product.getStatus() != 1) {
|
||||
return error("商品[" + orderItemDto.getProdName() + "]已下架");
|
||||
}
|
||||
|
||||
Long skuId = orderItemDto.getSkuId();
|
||||
if (skuId == null) {
|
||||
return error("请选择商品规格");
|
||||
}
|
||||
ProdSku sku = prodSkuService.getProdSkuBySkuId(skuId);
|
||||
if (sku == null || sku.getStatus() != 1) {
|
||||
return error("商品规格[" + orderItemDto.getSkuName() + "]已下架");
|
||||
}
|
||||
if (sku.getLatestInventory() == null || sku.getLatestInventory() < orderItemDto.getQuantity()) {
|
||||
return error("商品[" + orderItemDto.getProdName() + "]库存不足");
|
||||
}
|
||||
|
||||
// 创建订单项(sku_id 必须有值)
|
||||
OrderItem orderItem = new OrderItem();
|
||||
orderItem.setShopId(shopId);
|
||||
orderItem.setOrderNumber(orderNumber);
|
||||
orderItem.setProdId(orderItemDto.getProdId());
|
||||
orderItem.setSkuId(skuId);
|
||||
orderItem.setQuantity(orderItemDto.getQuantity());
|
||||
orderItem.setProdName(orderItemDto.getProdName());
|
||||
orderItem.setSkuName(orderItemDto.getSkuName());
|
||||
orderItem.setPic(orderItemDto.getPic());
|
||||
orderItem.setUnitPrice(orderItemDto.getUnitPrice());
|
||||
orderItem.setUserId(userId);
|
||||
orderItem.setTotalAmount(orderItemDto.getTotalAmount());
|
||||
orderItem.setCreateTime(now);
|
||||
orderItems.add(orderItem);
|
||||
|
||||
int count = orderItemDto.getQuantity();
|
||||
sku.setLatestInventory((sku.getLatestInventory() == null ? 0 : sku.getLatestInventory()) - count);
|
||||
sku.setReservedInventory((sku.getReservedInventory() == null ? 0 : sku.getReservedInventory()) + count);
|
||||
prodSkuService.updateById(sku);
|
||||
prodSkuService.removeSkuCacheBySkuId(skuId, orderItemDto.getProdId());
|
||||
prodSkuService.evictSkuListCache(orderItemDto.getProdId());
|
||||
|
||||
// 更新商品总库存(有则扣减)
|
||||
if (product.getInventory() != null) {
|
||||
product.setInventory(product.getInventory() - orderItemDto.getQuantity());
|
||||
productService.updateById(product);
|
||||
}
|
||||
|
||||
totalCount += orderItemDto.getQuantity();
|
||||
total += orderItemDto.getTotalAmount();
|
||||
orderProdName.append(orderItemDto.getProdName()).append(",");
|
||||
}
|
||||
|
||||
// 截取商品名称(最多100个字符)
|
||||
String prodName = orderProdName.toString();
|
||||
if (prodName.length() > 100) {
|
||||
prodName = prodName.substring(0, 100);
|
||||
}
|
||||
if (prodName.endsWith(",")) {
|
||||
prodName = prodName.substring(0, prodName.length() - 1);
|
||||
}
|
||||
|
||||
// 创建订单
|
||||
Order order = new Order();
|
||||
order.setShopId(shopId);
|
||||
order.setProdName(prodName);
|
||||
order.setUserId(userId);
|
||||
order.setOrderNumber(orderNumber);
|
||||
order.setTotalAmount(total);
|
||||
order.setActualTotalAmount(confirmDto.getActualTotal() != null ? confirmDto.getActualTotal() : total + transfee);
|
||||
order.setRemarks(remarks);
|
||||
order.setStatus(0); // 待付款
|
||||
order.setShippingFee(transfee);
|
||||
order.setOrderAddrId(orderAddrId);
|
||||
order.setQuantity(totalCount);
|
||||
order.setCreateTime(now);
|
||||
order.setUpdateTime(now);
|
||||
order.setDiscountAmount(confirmDto.getShopReduce() != null ? confirmDto.getShopReduce() : 0.0);
|
||||
order.setOrderItems(orderItems);
|
||||
|
||||
// 保存订单
|
||||
orderService.save(order);
|
||||
|
||||
// 订单日志:下单(待付款)
|
||||
if (shopOrderLogService != null) {
|
||||
shopOrderLogService.addLog(orderNumber, order.getId(), 0, null, null, null, userId, ApiSecurityUtils.getUserName());
|
||||
}
|
||||
|
||||
// 保存订单项
|
||||
for (OrderItem orderItem : orderItems) {
|
||||
orderItemService.save(orderItem);
|
||||
}
|
||||
|
||||
// 若启用且带了邀请码,绑定到该订单:写入用户id/用户名、订单编码,状态更新为已下单(1)
|
||||
if (inviteEnabled && inviteCode != null && !inviteCode.trim().isEmpty()) {
|
||||
String userName = ApiSecurityUtils.getUserName();
|
||||
inviteCodeService.bindToOrder(inviteCode.trim(), userId, userName, orderNumber);
|
||||
}
|
||||
|
||||
// 待支付 10 分钟倒计时写入 Redis
|
||||
long expireAt = orderUnpayCountdownService.put(orderNumber);
|
||||
|
||||
// 清除缓存
|
||||
OrderCacheUtil.remove(userId);
|
||||
|
||||
// 返回订单号及过期时间戳(前端倒计时用)
|
||||
OrderNumbersDto orderNumbersDto = new OrderNumbersDto(orderNumber);
|
||||
orderNumbersDto.setUnpayExpireAt(expireAt);
|
||||
return success(orderNumbersDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单号(使用时间戳+随机数)
|
||||
*/
|
||||
private String generateOrderNumber() {
|
||||
// 使用hutool的IdUtil生成唯一ID
|
||||
return String.valueOf(IdUtil.getSnowflake(1, 1).nextId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.service.IOrderService;
|
||||
import com.ruoyi.jyshop.service.IOrderUnpayCountdownService;
|
||||
import com.ruoyi.jyshop.utils.ApiSecurityUtils;
|
||||
import com.ruoyi.jyshop.vo.PayParam;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/pay")
|
||||
public class PayApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IOrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private IOrderUnpayCountdownService orderUnpayCountdownService;
|
||||
|
||||
/**
|
||||
* 支付接口
|
||||
* 注意:支付功能需要根据实际支付方式(微信、支付宝等)实现
|
||||
*/
|
||||
@PostMapping("/pay")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult pay(@RequestBody PayParam payParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
// 1. 验证参数
|
||||
if (payParam.getPayType() == null) {
|
||||
return error("支付方式不能为空");
|
||||
}
|
||||
if (payParam.getPayType() != 1 && payParam.getPayType() != 2) {
|
||||
return error("支付方式不正确(1=微信支付,2=支付宝)");
|
||||
}
|
||||
if (payParam.getOrderNumbers() == null || payParam.getOrderNumbers().trim().isEmpty()) {
|
||||
return error("订单号不能为空");
|
||||
}
|
||||
|
||||
// 2. 解析订单号(支持多个订单号,用逗号分隔)
|
||||
String[] orderNumberArray = payParam.getOrderNumbers().split(",");
|
||||
|
||||
// 3. 验证并更新订单
|
||||
for (String orderNumber : orderNumberArray) {
|
||||
orderNumber = orderNumber.trim();
|
||||
if (orderNumber.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 查询订单
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单[" + orderNumber + "]不存在");
|
||||
}
|
||||
|
||||
// 验证订单是否属于当前用户
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return error("无权操作该订单");
|
||||
}
|
||||
|
||||
// 验证订单状态(只有待支付状态才能支付)
|
||||
if (order.getStatus() == null || order.getStatus() != 0) {
|
||||
return error("订单[" + orderNumber + "]不是待支付状态,无法支付");
|
||||
}
|
||||
|
||||
// 写入订单支付方式:1=微信, 2=支付宝
|
||||
order.setPayType(payParam.getPayType());
|
||||
order.setUpdateTime(new Date());
|
||||
orderService.updateById(order);
|
||||
}
|
||||
|
||||
// 4. 构建支付信息(这里返回模拟数据,实际需要调用微信/支付宝SDK)
|
||||
Map<String, Object> payInfo = new HashMap<>();
|
||||
if (payParam.getPayType() == 1) {
|
||||
// 微信支付
|
||||
payInfo.put("payType", 1);
|
||||
payInfo.put("payTypeName", "微信支付");
|
||||
// TODO: 实际应该调用微信支付SDK,返回以下参数
|
||||
// payInfo.put("timeStamp", "...");
|
||||
// payInfo.put("nonceStr", "...");
|
||||
// payInfo.put("packageValue", "...");
|
||||
// payInfo.put("signType", "MD5");
|
||||
// payInfo.put("paySign", "...");
|
||||
payInfo.put("message", "微信支付功能待集成,当前为模拟支付");
|
||||
} else if (payParam.getPayType() == 2) {
|
||||
// 支付宝支付
|
||||
payInfo.put("payType", 2);
|
||||
payInfo.put("payTypeName", "支付宝");
|
||||
// TODO: 实际应该调用支付宝支付SDK,返回支付表单或支付URL
|
||||
// payInfo.put("payForm", "...");
|
||||
payInfo.put("message", "支付宝支付功能待集成,当前为模拟支付");
|
||||
}
|
||||
|
||||
return success(payInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通支付接口(直接支付成功,用于测试)
|
||||
*/
|
||||
@PostMapping("/normalPay")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult normalPay(@RequestBody PayParam payParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
// 验证参数
|
||||
if (payParam.getPayType() == null) {
|
||||
return error("支付方式不能为空");
|
||||
}
|
||||
if (payParam.getOrderNumbers() == null || payParam.getOrderNumbers().trim().isEmpty()) {
|
||||
return error("订单号不能为空");
|
||||
}
|
||||
|
||||
// 解析订单号
|
||||
String[] orderNumberArray = payParam.getOrderNumbers().split(",");
|
||||
|
||||
// 更新订单状态为已支付
|
||||
for (String orderNumber : orderNumberArray) {
|
||||
orderNumber = orderNumber.trim();
|
||||
if (orderNumber.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Order order = orderService.getOrderByOrderNumber(orderNumber);
|
||||
if (order == null) {
|
||||
return error("订单[" + orderNumber + "]不存在");
|
||||
}
|
||||
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return error("无权操作该订单");
|
||||
}
|
||||
|
||||
if (order.getStatus() == null || order.getStatus() != 0) {
|
||||
return error("订单[" + orderNumber + "]不是待支付状态,无法支付");
|
||||
}
|
||||
|
||||
// 更新订单状态为已支付
|
||||
order.setStatus(1); // 待发货
|
||||
// 写入订单支付方式:1=微信, 2=支付宝
|
||||
order.setPayType(payParam.getPayType());
|
||||
order.setUpdateTime(new Date());
|
||||
orderService.updateById(order);
|
||||
orderUnpayCountdownService.remove(orderNumber);
|
||||
}
|
||||
|
||||
return success("支付成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.jyshop.domain.Product;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplate;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.jyshop.service.IProductService;
|
||||
import com.ruoyi.jyshop.service.IProdSkuService;
|
||||
import com.ruoyi.jyshop.service.IShippingTemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 商品API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/prod")
|
||||
public class ProdApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IProductService productService;
|
||||
|
||||
@Autowired
|
||||
private IProdSkuService prodSkuService;
|
||||
|
||||
@Autowired
|
||||
private IShippingTemplateService shippingTemplateService;
|
||||
|
||||
/**
|
||||
* 通过分类id商品列表信息
|
||||
*/
|
||||
@GetMapping("/pageProd")
|
||||
public TableDataInfo prodList(@RequestParam(value = "categoryId", required = false) Long categoryId, Page<Product> page) {
|
||||
// 从请求参数中获取分页信息,设置到MyBatis-Plus的Page对象
|
||||
PageDomain pageDomain = TableSupport.getPageDomain();
|
||||
page.setCurrent(pageDomain.getPageNum());
|
||||
page.setSize(pageDomain.getPageSize());
|
||||
|
||||
// 构建查询条件:根据分类ID查询(如果categoryId为null,则查询所有),只查询上架的商品(status=1)
|
||||
LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<Product>()
|
||||
.eq(categoryId != null, Product::getCategoryId, categoryId) // categoryId不为null时才添加分类条件
|
||||
.eq(Product::getStatus, 1) // 只查询上架的商品
|
||||
.orderByDesc(Product::getUpdateTime); // 按上架时间倒序
|
||||
|
||||
// 执行分页查询
|
||||
IPage<Product> productPage = productService.page(page, queryWrapper);
|
||||
|
||||
// 使用IPage对象构建TableDataInfo,包含总数信息
|
||||
TableDataInfo dataTable = new TableDataInfo();
|
||||
dataTable.setCode(HttpStatus.SUCCESS);
|
||||
dataTable.setMsg("查询成功");
|
||||
dataTable.setRows(productPage.getRecords());
|
||||
dataTable.setTotal(productPage.getTotal());
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情信息
|
||||
*/
|
||||
@GetMapping("/product/info/{prodId}")
|
||||
public AjaxResult prodInfo(@PathVariable("prodId") Long prodId) {
|
||||
Product product = productService.getProductByProdId(prodId);
|
||||
if (product == null) {
|
||||
return success();
|
||||
}
|
||||
|
||||
List<ProdSku> skuList = prodSkuService.listByProdId(prodId);
|
||||
// 启用的sku列表
|
||||
List<ProdSku> useSkuList = skuList.stream()
|
||||
.filter(sku -> sku.getStatus() != null && sku.getStatus() == 1)
|
||||
.collect(Collectors.toList());
|
||||
// 页面库存展示用 latest_inventory,前端直接使用该字段
|
||||
product.setSkuList(useSkuList);
|
||||
|
||||
// 商品的配送方式
|
||||
if (product.getShippingType() != null) {
|
||||
try {
|
||||
Product.DeliveryModeVO deliveryModeVO = JSON.parseObject(product.getShippingType(), Product.DeliveryModeVO.class);
|
||||
// 有店铺配送的方式, 且存在运费模板,才返回运费模板的信息
|
||||
if (deliveryModeVO != null && deliveryModeVO.getHasShopDelivery() != null
|
||||
&& deliveryModeVO.getHasShopDelivery() && product.getShippingTemplateId() != null) {
|
||||
ShippingTemplate template = shippingTemplateService.getTemplateAndAllItems(product.getShippingTemplateId());
|
||||
product.setShopName(template != null ? template.getName() : null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 解析失败,忽略
|
||||
}
|
||||
}
|
||||
|
||||
return success(product);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新品推荐
|
||||
*/
|
||||
@GetMapping("/lastedProdPage")
|
||||
public TableDataInfo lastedProdPage(Page<Product> page) {
|
||||
// TODO: 需要扩展IProductService添加pageByPutAwayTime方法
|
||||
startPage();
|
||||
return getDataTable(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
import com.ruoyi.jyshop.service.IProdSkuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SKU规格API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/sku")
|
||||
public class SkuApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IProdSkuService prodSkuService;
|
||||
|
||||
/**
|
||||
* 通过prodId获取商品全部规格列表
|
||||
*/
|
||||
@GetMapping("/getSkuList")
|
||||
public AjaxResult getSkuListByProdId(@RequestParam("prodId") Long prodId) {
|
||||
List<ProdSku> skus = prodSkuService.list(new LambdaQueryWrapper<ProdSku>()
|
||||
.eq(ProdSku::getStatus, 1)
|
||||
// .eq(ProdSku::getIsDelete, 0)
|
||||
.eq(ProdSku::getProdId, prodId)
|
||||
);
|
||||
return success(skus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package com.ruoyi.jyshop.controller.api;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.jyshop.domain.UserAddr;
|
||||
import com.ruoyi.jyshop.service.IUserAddrService;
|
||||
import com.ruoyi.jyshop.utils.ApiSecurityUtils;
|
||||
import com.ruoyi.jyshop.vo.AddrParam;
|
||||
import com.ruoyi.jyshop.vo.UserAddrDto;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户地址API Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/shop/api/address")
|
||||
public class UserAddrApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IUserAddrService userAddrService;
|
||||
|
||||
/**
|
||||
* 用户地址列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list() {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
List<UserAddr> userAddrs = userAddrService.list(new LambdaQueryWrapper<UserAddr>()
|
||||
.eq(UserAddr::getUserId, userId)
|
||||
.orderByDesc(UserAddr::getIsDefaultAddr)
|
||||
.orderByDesc(UserAddr::getUpdateTime));
|
||||
List<UserAddrDto> userAddrDtos = BeanUtil.copyToList(userAddrs, UserAddrDto.class);
|
||||
return success(userAddrDtos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户地址
|
||||
*/
|
||||
@PostMapping("/addAddr")
|
||||
public AjaxResult addAddr(@Valid @RequestBody AddrParam addrParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
if (addrParam.getId() != null && addrParam.getId() != 0) {
|
||||
return error("该地址已存在");
|
||||
}
|
||||
long addrCount = userAddrService.count(new LambdaQueryWrapper<UserAddr>()
|
||||
.eq(UserAddr::getUserId, userId));
|
||||
UserAddr userAddr = BeanUtil.copyProperties(addrParam, UserAddr.class);
|
||||
|
||||
// 优先使用请求中的“设为默认”;未传或为首条时为首条则设为默认
|
||||
if (addrParam.getIsDefaultAddr() != null && addrParam.getIsDefaultAddr() == 1) {
|
||||
userAddr.setIsDefaultAddr(1);
|
||||
} else if (addrCount == 0) {
|
||||
userAddr.setIsDefaultAddr(1);
|
||||
} else {
|
||||
userAddr.setIsDefaultAddr(0);
|
||||
}
|
||||
userAddr.setUserId(userId);
|
||||
userAddr.setStatus(1);
|
||||
userAddr.setCreateTime(new Date());
|
||||
userAddr.setUpdateTime(new Date());
|
||||
userAddrService.save(userAddr);
|
||||
if (userAddr.getIsDefaultAddr() == 1) {
|
||||
// 取消其他地址的默认,仅保留当前新地址为默认
|
||||
userAddrService.updateDefaultUserAddr(userAddr.getId(), userId);
|
||||
}
|
||||
UserAddrDto dto = BeanUtil.copyProperties(userAddr, UserAddrDto.class);
|
||||
return success(dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户地址
|
||||
*/
|
||||
@PutMapping("/updateAddr")
|
||||
public AjaxResult updateAddr(@Valid @RequestBody AddrParam addrParam) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
|
||||
UserAddr dbUserAddr = userAddrService.getUserAddrByUserId(addrParam.getId(), userId);
|
||||
if (dbUserAddr == null) {
|
||||
return error("该地址已被删除");
|
||||
}
|
||||
|
||||
UserAddr userAddr = BeanUtil.copyProperties(addrParam, UserAddr.class);
|
||||
userAddr.setUserId(userId);
|
||||
userAddr.setUpdateTime(new Date());
|
||||
userAddrService.updateById(userAddr);
|
||||
// 若本次设为默认,取消其他地址的默认,仅保留当前地址为默认
|
||||
if (addrParam.getIsDefaultAddr() != null && addrParam.getIsDefaultAddr() == 1) {
|
||||
userAddrService.updateDefaultUserAddr(addrParam.getId(), userId);
|
||||
}
|
||||
return success("修改地址成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户地址
|
||||
*/
|
||||
@DeleteMapping("/deleteAddr/{addrId}")
|
||||
public AjaxResult deleteAddr(@PathVariable("addrId") Long addrId) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
|
||||
if (userAddr == null) {
|
||||
return error("该地址已被删除");
|
||||
}
|
||||
if (userAddr.getIsDefaultAddr() == 1) {
|
||||
return error("默认地址无法删除");
|
||||
}
|
||||
userAddrService.removeById(addrId);
|
||||
return success("删除地址成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认地址
|
||||
*/
|
||||
@PutMapping("/defaultAddr/{addrId}")
|
||||
public AjaxResult defaultAddr(@PathVariable("addrId") Long addrId) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
userAddrService.updateDefaultUserAddr(addrId, userId);
|
||||
return success("修改地址成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地址信息
|
||||
*/
|
||||
@GetMapping("/addrInfo/{addrId}")
|
||||
public AjaxResult addrInfo(@PathVariable("addrId") Long addrId) {
|
||||
String userId = ApiSecurityUtils.getUserId();
|
||||
if (userId == null) {
|
||||
return error("用户未登录");
|
||||
}
|
||||
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
|
||||
if (userAddr == null) {
|
||||
throw new ServiceException("该地址已被删除");
|
||||
}
|
||||
UserAddrDto userAddrDto = BeanUtil.copyProperties(userAddr, UserAddrDto.class);
|
||||
return success(userAddrDto);
|
||||
}
|
||||
}
|
||||
38
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Area.java
Normal file
38
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Area.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 区域对象 shop_area
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_area")
|
||||
public class Area implements Serializable {
|
||||
private static final long serialVersionUID = -6013320537436191451L;
|
||||
|
||||
@TableId("id")
|
||||
@Excel(name = "地区id")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "地区名称")
|
||||
private String name;
|
||||
|
||||
@Excel(name = "地区上级id")
|
||||
private Long parentId;
|
||||
|
||||
@Excel(name = "地区层级")
|
||||
private Integer level;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<Area> areas;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 附件文件对象 shop_attach_file
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_attach_file")
|
||||
public class AttachFile implements Serializable {
|
||||
|
||||
@TableId(value = "file_id", type = IdType.AUTO)
|
||||
@Excel(name = "文件ID")
|
||||
private Long fileId;
|
||||
|
||||
@Excel(name = "文件路径")
|
||||
private String filePath;
|
||||
|
||||
@Excel(name = "文件类型")
|
||||
private String fileType;
|
||||
|
||||
@Excel(name = "文件大小")
|
||||
private Integer fileSize;
|
||||
|
||||
@Excel(name = "上传时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date uploadTime;
|
||||
|
||||
@Excel(name = "文件关联的表主键id")
|
||||
private Long fileJoinId;
|
||||
|
||||
/**
|
||||
* 文件关联表类型:1 商品表
|
||||
*/
|
||||
@Excel(name = "文件关联表类型")
|
||||
private Integer fileJoinType;
|
||||
}
|
||||
50
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Basket.java
Normal file
50
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Basket.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 购物车对象 shop_basket
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_basket")
|
||||
public class Basket implements Serializable {
|
||||
|
||||
@TableId
|
||||
@Excel(name = "购物车ID")
|
||||
private Long basketId;
|
||||
|
||||
@Excel(name = "店铺ID")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "产品ID")
|
||||
private Long prodId;
|
||||
|
||||
@Excel(name = "SkuID")
|
||||
private Long skuId;
|
||||
|
||||
@Excel(name = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "购物车产品个数")
|
||||
private Integer basketCount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "购物时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date basketDate;
|
||||
|
||||
@Excel(name = "满减活动ID")
|
||||
private Long discountId;
|
||||
|
||||
@Excel(name = "分销推广人卡号")
|
||||
private String distributionCardNo;
|
||||
}
|
||||
57
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Brand.java
Normal file
57
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Brand.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 品牌对象 shop_brand
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_brand")
|
||||
public class Brand implements Serializable {
|
||||
|
||||
@TableId
|
||||
@Excel(name = "品牌ID")
|
||||
private Long brandId;
|
||||
|
||||
@Excel(name = "品牌名称")
|
||||
private String brandName;
|
||||
|
||||
@Excel(name = "图片路径")
|
||||
private String brandPic;
|
||||
|
||||
@Excel(name = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "备注")
|
||||
private String memo;
|
||||
|
||||
@Excel(name = "顺序")
|
||||
private Integer seq;
|
||||
|
||||
@Excel(name = "状态", readConverterExp = "1=正常,0=下线")
|
||||
private Integer status;
|
||||
|
||||
@Excel(name = "简要描述")
|
||||
private String brief;
|
||||
|
||||
@Excel(name = "记录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date recTime;
|
||||
|
||||
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
@Excel(name = "品牌首字母")
|
||||
private String firstChar;
|
||||
|
||||
@Excel(name = "内容")
|
||||
private String content;
|
||||
}
|
||||
93
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Category.java
Normal file
93
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Category.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类对象 shop_category
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_category")
|
||||
public class Category implements Serializable {
|
||||
|
||||
@TableId("id")
|
||||
@Excel(name = "类目ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "父节点")
|
||||
private Long parentId = 0L;
|
||||
|
||||
@Excel(name = "产品类目名称")
|
||||
private String name;
|
||||
|
||||
@Excel(name = "类目图标")
|
||||
private String icon;
|
||||
|
||||
@Excel(name = "类目的显示图片")
|
||||
private String pic;
|
||||
|
||||
@Excel(name = "排序")
|
||||
private Integer seq;
|
||||
|
||||
@Excel(name = "状态", readConverterExp = "1=正常,0=下线")
|
||||
private Integer status;
|
||||
|
||||
@TableField("create_time")
|
||||
@Excel(name = "记录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@Excel(name = "分类层级")
|
||||
private Integer level;
|
||||
|
||||
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 品牌id列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Long> brandIds;
|
||||
|
||||
/**
|
||||
* 参数id列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Long> attributeIds;
|
||||
|
||||
/**
|
||||
* 品牌列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Brand> brands;
|
||||
|
||||
/**
|
||||
* 参数列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Object> prodProps;
|
||||
|
||||
/**
|
||||
* 商品列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Object> products;
|
||||
|
||||
/**
|
||||
* 子分类列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Category> categories;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 分类品牌关联对象 shop_category_brand
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_category_brand")
|
||||
public class CategoryBrand implements Serializable {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 分类id
|
||||
*/
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 品牌id
|
||||
*/
|
||||
private Long brandId;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 分类属性关联对象 shop_category_prop
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_category_prop")
|
||||
public class CategoryProp implements Serializable {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 分类id
|
||||
*/
|
||||
private Long categoryId;
|
||||
|
||||
/**
|
||||
* 商品属性id即表shop_prod_prop中的prop_id
|
||||
*/
|
||||
private Long propId;
|
||||
}
|
||||
39
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Delivery.java
Normal file
39
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Delivery.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 物流公司对象 shop_delivery
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_delivery")
|
||||
public class Delivery implements Serializable {
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long dvyId;
|
||||
|
||||
@Excel(name = "物流公司名称")
|
||||
private String dvyName;
|
||||
|
||||
@Excel(name = "公司主页")
|
||||
private String companyHomeUrl;
|
||||
|
||||
@Excel(name = "建立时间")
|
||||
private Date recTime;
|
||||
|
||||
@Excel(name = "修改时间")
|
||||
private Date modifyTime;
|
||||
|
||||
@Excel(name = "物流查询接口")
|
||||
private String queryUrl;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 商城邀请码 shop_invite_code
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_invite_code")
|
||||
public class InviteCode implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "邀请码")
|
||||
private String code;
|
||||
|
||||
@Excel(name = "使用的用户ID")
|
||||
private Long usedUserId;
|
||||
|
||||
@Excel(name = "使用的用户名")
|
||||
private String usedUserName;
|
||||
|
||||
@Excel(name = "订单编码")
|
||||
private String orderNumber;
|
||||
|
||||
@Excel(name = "状态", readConverterExp = "0=初始,1=已下单,2=已支付")
|
||||
private Integer status;
|
||||
|
||||
@Excel(name = "创建人")
|
||||
private String createBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "创建时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@Excel(name = "修改人")
|
||||
private String updateBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "修改时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
143
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Order.java
Normal file
143
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Order.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单对象 shop_order
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_order")
|
||||
public class Order implements Serializable {
|
||||
private static final long serialVersionUID = 6222259729062826852L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "订单ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "产品名称")
|
||||
private String prodName;
|
||||
|
||||
@Excel(name = "订购用户ID")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "订购流水号")
|
||||
private String orderNumber;
|
||||
|
||||
@Excel(name = "总值")
|
||||
private Double totalAmount;
|
||||
|
||||
@Excel(name = "实际总值")
|
||||
private Double actualTotalAmount;
|
||||
|
||||
@Excel(name = "订单备注")
|
||||
private String remarks;
|
||||
|
||||
@Excel(name = "订单状态", readConverterExp = "-1=已取消,0=待付款,1=待发货,2=待收货,3=完成,4=已退款")
|
||||
private Integer status;
|
||||
|
||||
@Excel(name = "支付方式", readConverterExp = "1=微信支付,2=支付宝")
|
||||
private Integer payType;
|
||||
|
||||
@Excel(name = "订单运费")
|
||||
private Double shippingFee;
|
||||
|
||||
@Excel(name = "用户订单地址Id")
|
||||
private Long orderAddrId;
|
||||
|
||||
@Excel(name = "订单商品总数")
|
||||
private Integer quantity;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "订购时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "订单更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/** 微信 Native 预下单成功时间(有待支付二维码,配合定时查单) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date wxPrepayTime;
|
||||
|
||||
/** 微信查单次数(支付中状态最多查 10 次,仍未成功则改为支付失败) */
|
||||
private Integer wxPrepayQueryCount;
|
||||
|
||||
/** 预下单金额(分),与微信侧一致 */
|
||||
private Long wxPrepayTotalFen;
|
||||
|
||||
/** 关联 jy_pay_log.id */
|
||||
private Long wxPayLogId;
|
||||
|
||||
/** 微信退款申请提交成功时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date wxRefundApplyTime;
|
||||
|
||||
/** 商户退款单号 out_refund_no */
|
||||
private String wxRefundOutRefundNo;
|
||||
|
||||
/** 微信退款单号 refund_id */
|
||||
private String wxRefundId;
|
||||
|
||||
/** 申请退款金额(分) */
|
||||
private Long wxRefundAmountFen;
|
||||
|
||||
/** 原订单总金额(分) */
|
||||
private Long wxRefundTotalFen;
|
||||
|
||||
/** 申请接口返回状态:PROCESSING、SUCCESS 等 */
|
||||
private String wxRefundApplyStatus;
|
||||
|
||||
/** 退款原因 */
|
||||
private String wxRefundReason;
|
||||
|
||||
@Excel(name = "优惠总额")
|
||||
private Double discountAmount;
|
||||
|
||||
/** 是否已核销:0-未核销 1-已核销 */
|
||||
private Integer verified;
|
||||
|
||||
/**
|
||||
* 店铺名称(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String shopName;
|
||||
|
||||
/**
|
||||
* 订单项列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<OrderItem> orderItems;
|
||||
|
||||
/**
|
||||
* 订单地址(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private OrderAddr orderAddr;
|
||||
|
||||
/**
|
||||
* 待支付倒计时过期时间戳(毫秒),仅待付款列表返回,不映射到数据库
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Long unpayExpireAt;
|
||||
|
||||
/**
|
||||
* 单据日志列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<ShopOrderLog> orderLogs;
|
||||
}
|
||||
68
jy-shop/src/main/java/com/ruoyi/jyshop/domain/OrderAddr.java
Normal file
68
jy-shop/src/main/java/com/ruoyi/jyshop/domain/OrderAddr.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单地址对象 shop_order_addr
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_order_addr")
|
||||
public class OrderAddr implements Serializable {
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "用户地址ID")
|
||||
private Long userAddrId;
|
||||
|
||||
@Excel(name = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "收货人")
|
||||
private String receiver;
|
||||
|
||||
@Excel(name = "省")
|
||||
private String province;
|
||||
|
||||
@Excel(name = "城市")
|
||||
private String city;
|
||||
|
||||
@Excel(name = "区")
|
||||
private String area;
|
||||
|
||||
@Excel(name = "地址")
|
||||
private String addr;
|
||||
|
||||
@Excel(name = "邮编")
|
||||
private String postCode;
|
||||
|
||||
@Excel(name = "省ID")
|
||||
private Long provinceId;
|
||||
|
||||
@Excel(name = "城市ID")
|
||||
private Long cityId;
|
||||
|
||||
@Excel(name = "区域ID")
|
||||
private Long areaId;
|
||||
|
||||
@Excel(name = "手机")
|
||||
private String mobile;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "建立时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@Excel(name = "版本号")
|
||||
private Integer version;
|
||||
}
|
||||
67
jy-shop/src/main/java/com/ruoyi/jyshop/domain/OrderItem.java
Normal file
67
jy-shop/src/main/java/com/ruoyi/jyshop/domain/OrderItem.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单项对象 shop_order_item
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_order_item")
|
||||
public class OrderItem implements Serializable {
|
||||
private static final long serialVersionUID = 7307405761190788407L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
@Excel(name = "订单项ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "店铺ID")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "订单编号")
|
||||
private String orderNumber;
|
||||
|
||||
@Excel(name = "产品ID")
|
||||
private Long prodId;
|
||||
|
||||
@Excel(name = "产品SkuID")
|
||||
private Long skuId;
|
||||
|
||||
@Excel(name = "商品数量")
|
||||
private Integer quantity;
|
||||
|
||||
@Excel(name = "产品名称")
|
||||
private String prodName;
|
||||
|
||||
@Excel(name = "sku名称")
|
||||
private String skuName;
|
||||
|
||||
@Excel(name = "产品主图片路径")
|
||||
private String pic;
|
||||
|
||||
@Excel(name = "产品单价")
|
||||
private Double unitPrice;
|
||||
|
||||
@Excel(name = "用户Id")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "商品总金额")
|
||||
private Double totalAmount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "购物时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@Excel(name = "推广员用户ID")
|
||||
private String distributorUserId;
|
||||
}
|
||||
53
jy-shop/src/main/java/com/ruoyi/jyshop/domain/PickAddr.java
Normal file
53
jy-shop/src/main/java/com/ruoyi/jyshop/domain/PickAddr.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 自提地址对象 shop_pick_addr
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_pick_addr")
|
||||
public class PickAddr implements Serializable {
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long addrId;
|
||||
|
||||
@Excel(name = "自提点名称")
|
||||
private String addrName;
|
||||
|
||||
@Excel(name = "地址")
|
||||
private String addr;
|
||||
|
||||
@Excel(name = "手机")
|
||||
private String mobile;
|
||||
|
||||
@Excel(name = "省份ID")
|
||||
private Long provinceId;
|
||||
|
||||
@Excel(name = "省份")
|
||||
private String province;
|
||||
|
||||
@Excel(name = "城市ID")
|
||||
private Long cityId;
|
||||
|
||||
@Excel(name = "城市")
|
||||
private String city;
|
||||
|
||||
@Excel(name = "区/县ID")
|
||||
private Long areaId;
|
||||
|
||||
@Excel(name = "区/县")
|
||||
private String area;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
}
|
||||
39
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdProp.java
Normal file
39
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdProp.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品属性对象 shop_prod_prop
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_prod_prop")
|
||||
public class ProdProp implements Serializable {
|
||||
private static final long serialVersionUID = -8761177918672000191L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "主键")
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "属性名称不能为空")
|
||||
@Excel(name = "属性名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 属性明细列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
@NotEmpty(message = "规格属性值不能为空")
|
||||
private List<ProdPropDtl> prodPropDtls;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 商品属性明细对象 shop_prod_prop_dtl
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_prod_prop_dtl")
|
||||
public class ProdPropDtl implements Serializable {
|
||||
private static final long serialVersionUID = 6604406039354172708L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "主键")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "属性值")
|
||||
private String val;
|
||||
|
||||
@Excel(name = "属性ID")
|
||||
private Long propId;
|
||||
}
|
||||
68
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdSku.java
Normal file
68
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdSku.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 商品SKU对象 shop_prod_sku
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_prod_sku")
|
||||
public class ProdSku implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3302315892644536259L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "单品ID")
|
||||
private Long id;
|
||||
@Excel(name = "商品ID")
|
||||
private Long prodId;
|
||||
@Excel(name = "销售属性组合字符串")
|
||||
private String prop;
|
||||
@Excel(name = "原价")
|
||||
private Double regularPrice;
|
||||
@Excel(name = "价格")
|
||||
private Double latestPrice;
|
||||
@Excel(name = "预留库存")
|
||||
@TableField("reserved_inventory")
|
||||
private Integer reservedInventory;
|
||||
@Excel(name = "实际库存")
|
||||
@TableField("latest_inventory")
|
||||
private Integer latestInventory;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "记录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
@Excel(name = "商家编码")
|
||||
private String productCode;
|
||||
@Excel(name = "商品条形码")
|
||||
private String productBarcode;
|
||||
@Excel(name = "sku图片")
|
||||
private String pic;
|
||||
@Excel(name = "sku名称")
|
||||
private String name;
|
||||
@Excel(name = "商品名称")
|
||||
private String prodName;
|
||||
@Excel(name = "版本")
|
||||
private Integer version;
|
||||
@Excel(name = "重量")
|
||||
private Double weight;
|
||||
@Excel(name = "体积")
|
||||
private Double volume;
|
||||
@Excel(name = "状态", readConverterExp = "0=禁用,1=启用")
|
||||
private Integer status;
|
||||
// @Excel(name = "删除状态", readConverterExp = "0=正常,1=已删除")
|
||||
// private Integer isDelete;
|
||||
}
|
||||
42
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdTag.java
Normal file
42
jy-shop/src/main/java/com/ruoyi/jyshop/domain/ProdTag.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 商品-标签关联 shop_prod_tag
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_prod_tag")
|
||||
public class ProdTag implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "标签id")
|
||||
private Long tagId;
|
||||
|
||||
@Excel(name = "商品id")
|
||||
private Long prodId;
|
||||
|
||||
@Excel(name = "状态", readConverterExp = "1=正常,0=删除")
|
||||
private Integer status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
}
|
||||
114
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Product.java
Normal file
114
jy-shop/src/main/java/com/ruoyi/jyshop/domain/Product.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.Version;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品对象 shop_prod
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_prod")
|
||||
public class Product implements Serializable {
|
||||
private static final long serialVersionUID = -4644407386444894349L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "商品ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
|
||||
@Excel(name = "商品名称")
|
||||
private String name;
|
||||
|
||||
@Excel(name = "原价")
|
||||
private Double regularPrice;
|
||||
|
||||
@Excel(name = "现价")
|
||||
private Double latestPrice;
|
||||
|
||||
@Excel(name = "简要描述")
|
||||
private String shortDescription;
|
||||
|
||||
@Excel(name = "商品主图")
|
||||
private String mainPic;
|
||||
|
||||
@Excel(name = "商品图片")
|
||||
private String detailedPics;
|
||||
|
||||
@Excel(name = "状态", readConverterExp = "1=正常,-1=删除,0=下架")
|
||||
private Integer status;
|
||||
|
||||
@Excel(name = "商品分类")
|
||||
private Long categoryId;
|
||||
|
||||
@Excel(name = "库存量")
|
||||
private Integer inventory;
|
||||
|
||||
@Excel(name = "配送方式json")
|
||||
private String shippingType;
|
||||
|
||||
@Excel(name = "运费模板id")
|
||||
private Long shippingTemplateId;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "录入时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
@Excel(name = "详细描述")
|
||||
private String detailedDescription;
|
||||
|
||||
@Version
|
||||
@Excel(name = "版本")
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* sku列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<ProdSku> skuList;
|
||||
|
||||
/**
|
||||
* 店铺名称(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String shopName;
|
||||
|
||||
/**
|
||||
* 标签列表(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Long> tagList;
|
||||
|
||||
/**
|
||||
* 配送方式VO
|
||||
*/
|
||||
@Data
|
||||
public static class DeliveryModeVO {
|
||||
/**
|
||||
* 用户自提
|
||||
*/
|
||||
private Boolean hasUserPickUp;
|
||||
|
||||
/**
|
||||
* 店铺配送
|
||||
*/
|
||||
private Boolean hasShopDelivery;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板对象 shop_shipping_template
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_shipping_template")
|
||||
public class ShippingTemplate implements Serializable {
|
||||
private static final long serialVersionUID = 1876655654053364580L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "运费模板名称")
|
||||
private String name;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@Excel(name = "店铺id")
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 收费方式(0 按件数,1 按重量 2 按体积)
|
||||
*/
|
||||
@Excel(name = "收费方式", readConverterExp = "0=按件数,1=按重量,2=按体积")
|
||||
private Integer billingMethod;
|
||||
|
||||
/**
|
||||
* 是否包邮 0:不包邮 1:包邮
|
||||
*/
|
||||
@Excel(name = "是否包邮", readConverterExp = "0=不包邮,1=包邮")
|
||||
private Integer isFreeShipping;
|
||||
|
||||
/**
|
||||
* 是否含有包邮条件
|
||||
*/
|
||||
@Excel(name = "是否含有包邮条件")
|
||||
private Integer freeCondition;
|
||||
|
||||
/**
|
||||
* 指定条件包邮项(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<ShippingTemplateFree> transfeeFrees;
|
||||
|
||||
/**
|
||||
* 运费计费规则(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<ShippingTemplatePaid> transfees;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板包邮条件对象 shop_shipping_template_free
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_shipping_template_free")
|
||||
public class ShippingTemplateFree implements Serializable {
|
||||
private static final long serialVersionUID = -2811714952219888223L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "运费模板id")
|
||||
private Long templateId;
|
||||
|
||||
@Excel(name = "包邮方式")
|
||||
private Integer freeShippingMethod;
|
||||
|
||||
@Excel(name = "需满金额")
|
||||
private Double amount;
|
||||
|
||||
@Excel(name = "需满件数")
|
||||
private Double quantity;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<Area> freeCityList;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运费模板包邮区域明细 shop_shipping_template_free_dtl
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_shipping_template_free_dtl")
|
||||
public class ShippingTemplateFreeDtl implements Serializable {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/** 包邮条件id */
|
||||
private Long parentId;
|
||||
|
||||
/** 区域id */
|
||||
private Long areaId;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板计费规则对象 shop_shipping_template_paid
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_shipping_template_paid")
|
||||
public class ShippingTemplatePaid implements Serializable {
|
||||
private static final long serialVersionUID = 8039640964056626028L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "运费模板id")
|
||||
private Long templateId;
|
||||
|
||||
@Excel(name = "首件/首重/首体积")
|
||||
private Double initialQuantity;
|
||||
|
||||
@Excel(name = "首费")
|
||||
private Double initialCharge;
|
||||
|
||||
@Excel(name = "续件/续重/续体积")
|
||||
private Double extraQuantity;
|
||||
|
||||
@Excel(name = "续费")
|
||||
private Double extraCharge;
|
||||
|
||||
/**
|
||||
* 指定区域明细(不映射到数据库)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private List<Area> cityList;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 运费模板计费区域明细 shop_shipping_template_paid_dtl
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_shipping_template_paid_dtl")
|
||||
public class ShippingTemplatePaidDtl implements Serializable {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/** 计费规则id */
|
||||
private Long parentId;
|
||||
|
||||
/** 区域id */
|
||||
private Long areaId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String areaName;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 发票基本信息 shop_invoice_basic
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_invoice_basic")
|
||||
public class ShopInvoiceBasic implements Serializable {
|
||||
|
||||
@TableId("id")
|
||||
private Long id;
|
||||
|
||||
private String invoiceType;
|
||||
|
||||
private String invoiceCode;
|
||||
|
||||
private String invoiceNumber;
|
||||
|
||||
private String invoiceDate;
|
||||
|
||||
private String machineNumber;
|
||||
|
||||
private String checkCode;
|
||||
|
||||
private String buyerName;
|
||||
|
||||
private String buyerTaxNo;
|
||||
|
||||
private String totalAmountLower;
|
||||
|
||||
private String sellerName;
|
||||
|
||||
private String sellerTaxNo;
|
||||
|
||||
private String fileUrl;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String createBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
private String updateBy;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单资金流水表 shop_order_fund_flow
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_order_fund_flow")
|
||||
public class ShopOrderFundFlow implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 流水号 */
|
||||
private String flowNo;
|
||||
|
||||
/** 业务订单号 */
|
||||
private String orderNo;
|
||||
|
||||
/** 微信支付订单号 */
|
||||
private String transactionId;
|
||||
|
||||
/** 微信退款单号 */
|
||||
private String refundId;
|
||||
|
||||
/** 流水类型:1=付款 2=退款 */
|
||||
private Integer flowType;
|
||||
|
||||
/** 变动金额(元) */
|
||||
private BigDecimal amount;
|
||||
|
||||
/** 变动后余额 */
|
||||
private BigDecimal balanceAfter;
|
||||
|
||||
/** 币种 */
|
||||
private String currency;
|
||||
|
||||
/** 支付渠道 */
|
||||
private String payChannel;
|
||||
|
||||
/** 状态:1=成功 2=失败 3=处理中 */
|
||||
private Integer status;
|
||||
|
||||
/** 微信回调时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date callbackTime;
|
||||
|
||||
/** 微信回调原始报文 */
|
||||
private String callbackRaw;
|
||||
|
||||
/** 回调关键数据(JSON) */
|
||||
private String callbackData;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单日志表 shop_order_log
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_order_log")
|
||||
public class ShopOrderLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 订单号 */
|
||||
private String orderNo;
|
||||
|
||||
/** 订单ID(冗余) */
|
||||
private Long orderId;
|
||||
|
||||
/** 订单状态: 0待付款 11支付失败 1待发货 2待收货 3已收货 4已取消 5发起退款 6发起退款退货 7同意退款退货 8退货中 9已退货 10已退款 */
|
||||
private Integer status;
|
||||
|
||||
/** 关联资金流水 shop_order_fund_flow.id */
|
||||
private Long flowId;
|
||||
|
||||
/** 物流公司 */
|
||||
private String logisticsCompany;
|
||||
|
||||
/** 物流单号 */
|
||||
private String logisticsNo;
|
||||
|
||||
/** 操作人ID */
|
||||
private String operatorId;
|
||||
|
||||
/** 操作人名称 */
|
||||
private String operatorName;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
}
|
||||
78
jy-shop/src/main/java/com/ruoyi/jyshop/domain/UserAddr.java
Normal file
78
jy-shop/src/main/java/com/ruoyi/jyshop/domain/UserAddr.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.ruoyi.jyshop.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 用户地址对象 shop_user_addr
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Data
|
||||
@TableName("shop_user_addr")
|
||||
public class UserAddr implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId
|
||||
@Excel(name = "地址ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@Excel(name = "收货人")
|
||||
private String receiver;
|
||||
|
||||
@Excel(name = "省ID")
|
||||
private Long provinceId;
|
||||
|
||||
@Excel(name = "省")
|
||||
private String province;
|
||||
|
||||
@Excel(name = "城市")
|
||||
private String city;
|
||||
|
||||
@Excel(name = "城市ID")
|
||||
private Long cityId;
|
||||
|
||||
@Excel(name = "区")
|
||||
private String area;
|
||||
|
||||
@Excel(name = "区ID")
|
||||
private Long areaId;
|
||||
|
||||
@Excel(name = "邮编")
|
||||
private String postCode;
|
||||
|
||||
@Excel(name = "地址")
|
||||
private String addr;
|
||||
|
||||
@Excel(name = "手机")
|
||||
private String mobile;
|
||||
|
||||
@Excel(name = "状态,1正常,0无效")
|
||||
private Integer status;
|
||||
|
||||
@Excel(name = "是否默认地址 1是")
|
||||
private Integer isDefaultAddr;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "建立时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Excel(name = "版本号")
|
||||
private Integer version;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.enums;
|
||||
|
||||
/**
|
||||
* 地区层级枚举
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public enum AreaLevelEnum {
|
||||
|
||||
/**
|
||||
* 第一层
|
||||
*/
|
||||
FIRST_LEVEL(1),
|
||||
|
||||
/**
|
||||
* 第二层
|
||||
*/
|
||||
SECOND_LEVEL(2),
|
||||
|
||||
/**
|
||||
* 第三层
|
||||
*/
|
||||
THIRD_LEVEL(3);
|
||||
|
||||
private Integer num;
|
||||
|
||||
public Integer value() {
|
||||
return num;
|
||||
}
|
||||
|
||||
AreaLevelEnum(Integer num) {
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public static AreaLevelEnum instance(Integer value) {
|
||||
AreaLevelEnum[] enums = values();
|
||||
for (AreaLevelEnum statusEnum : enums) {
|
||||
if (statusEnum.value().equals(value)) {
|
||||
return statusEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.ruoyi.jyshop.enums;
|
||||
|
||||
/**
|
||||
* 订单状态枚举
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public enum OrderStatus {
|
||||
|
||||
/**
|
||||
* 没有付款.待付款
|
||||
*/
|
||||
UNPAY(0),
|
||||
|
||||
/**
|
||||
* 已经付款,但卖家没有发货.待发货
|
||||
*/
|
||||
PADYED(1),
|
||||
|
||||
/**
|
||||
* 发货,导致实际库存减少,没有确认收货.待收货
|
||||
*/
|
||||
CONSIGNMENT(2),
|
||||
|
||||
/**
|
||||
* 收货,没有评价.待评价
|
||||
*/
|
||||
CONFIRM(3),
|
||||
|
||||
/**
|
||||
* 交易失败.,还原库存
|
||||
*/
|
||||
CLOSE(4),
|
||||
|
||||
/**
|
||||
* 已取消(用户取消待付款订单)
|
||||
*/
|
||||
CANCELLED(5);
|
||||
|
||||
private Integer num;
|
||||
|
||||
public Integer value() {
|
||||
return num;
|
||||
}
|
||||
|
||||
OrderStatus(Integer num) {
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public static OrderStatus instance(Integer value) {
|
||||
OrderStatus[] enums = values();
|
||||
for (OrderStatus statusEnum : enums) {
|
||||
if (statusEnum.value().equals(value)) {
|
||||
return statusEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.jyshop.enums;
|
||||
|
||||
/**
|
||||
* 商品规格参数、属性类型枚举
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public enum ProdPropRule {
|
||||
|
||||
// 规格属性 (用于商品商品发布时,关联sku)
|
||||
SPEC(1),
|
||||
|
||||
// 规格参数(用于商品搜索时,与分类关联搜索)
|
||||
ATTRIBUTE(2);
|
||||
|
||||
private Integer num;
|
||||
|
||||
public Integer value() {
|
||||
return num;
|
||||
}
|
||||
|
||||
ProdPropRule(Integer num) {
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public static ProdPropRule instance(Integer value) {
|
||||
ProdPropRule[] enums = values();
|
||||
for (ProdPropRule statusEnum : enums) {
|
||||
if (statusEnum.value().equals(value)) {
|
||||
return statusEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Area;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 区域Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface AreaMapper extends BaseMapper<Area> {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.AttachFile;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 附件文件Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface AttachFileMapper extends BaseMapper<AttachFile> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Basket;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 购物车Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface BasketMapper extends BaseMapper<Basket> {
|
||||
|
||||
/**
|
||||
* 获取购物车中拥有某件商品的用户,用于清除该用户购物车的缓存
|
||||
* @param prodId 商品id
|
||||
* @return 用户id列表
|
||||
*/
|
||||
List<String> listUserIdByProdId(@Param("prodId") Long prodId);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Brand;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 品牌Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface BrandMapper extends BaseMapper<Brand> {
|
||||
|
||||
/**
|
||||
* 根据品牌名称获取品牌
|
||||
* @param brandName 品牌名称
|
||||
* @return 品牌信息
|
||||
*/
|
||||
Brand getByBrandName(@Param("brandName") String brandName);
|
||||
|
||||
/**
|
||||
* 根据分类id获取品牌列表
|
||||
* @param categoryId 分类id
|
||||
* @return 品牌列表
|
||||
*/
|
||||
List<Brand> listByCategoryId(@Param("categoryId") Long categoryId);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Category;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface CategoryMapper extends BaseMapper<Category> {
|
||||
|
||||
/**
|
||||
* 根据父级id获取分类列表
|
||||
*
|
||||
* @param parentId 父级ID
|
||||
* @return 分类列表
|
||||
*/
|
||||
List<Category> listByParentId(@Param("parentId") Long parentId);
|
||||
|
||||
/**
|
||||
* 根据店铺id获取分类列表
|
||||
*
|
||||
* @param shopId 店铺ID
|
||||
* @return 分类列表
|
||||
*/
|
||||
List<Category> tableCategory(@Param("shopId") Long shopId);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.CategoryProp;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类属性关联Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface CategoryPropMapper extends BaseMapper<CategoryProp> {
|
||||
|
||||
/**
|
||||
* 插入分类属性
|
||||
* @param categoryId 分类ID
|
||||
* @param propIds 属性ID列表
|
||||
*/
|
||||
void insertCategoryProp(@Param("categoryId") Long categoryId, @Param("propIds") List<Long> propIds);
|
||||
|
||||
/**
|
||||
* 根据分类id删除分类属性
|
||||
* @param categoryId 分类ID
|
||||
*/
|
||||
void deleteByCategoryId(@Param("categoryId") Long categoryId);
|
||||
|
||||
/**
|
||||
* 根据属性id删除分类属性
|
||||
* @param propId 属性ID
|
||||
*/
|
||||
void deleteByPropId(@Param("propId") Long propId);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Delivery;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 物流公司Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface DeliveryMapper extends BaseMapper<Delivery> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.InviteCode;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface InviteCodeMapper extends BaseMapper<InviteCode> {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.OrderAddr;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单地址Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderAddrMapper extends BaseMapper<OrderAddr> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.OrderItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单项Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderItemMapper extends BaseMapper<OrderItem> {
|
||||
|
||||
/**
|
||||
* 根据订单编号获取订单项
|
||||
* @param orderNumber 订单编号
|
||||
* @return 订单项列表
|
||||
*/
|
||||
List<OrderItem> listByOrderNumber(@Param("orderNumber") String orderNumber);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.utils.PageAdapter;
|
||||
import com.ruoyi.jyshop.vo.OrderParam;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderMapper extends BaseMapper<Order> {
|
||||
|
||||
/**
|
||||
* 根据订单编号获取订单
|
||||
* @param orderNumber 订单编号
|
||||
* @return 订单信息
|
||||
*/
|
||||
Order getOrderByOrderNumber(@Param("orderNumber") String orderNumber);
|
||||
|
||||
/**
|
||||
* 根据参数和时间获取订单列表
|
||||
* @param order 订单参数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 订单列表
|
||||
*/
|
||||
List<Order> listOrdersDetailByOrder(@Param("order") Order order, @Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
|
||||
/**
|
||||
* 根据分页参数和订单参数获取订单列表
|
||||
* @param adapter 分页适配器
|
||||
* @param orderParam 订单参数
|
||||
* @return 订单列表
|
||||
*/
|
||||
List<Order> listOrdersDetailByOrderParam(@Param("adapter") PageAdapter adapter, @Param("orderParam") OrderParam orderParam);
|
||||
|
||||
/**
|
||||
* 根据订单参数获取订单数
|
||||
* @param orderParam 订单参数
|
||||
* @return 订单数量
|
||||
*/
|
||||
Long countOrderDetail(@Param("orderParam") OrderParam orderParam);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.PickAddr;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 自提地址Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface PickAddrMapper extends BaseMapper<PickAddr> {
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ProdPropDtl;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品属性明细Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProdPropDtlMapper extends BaseMapper<ProdPropDtl> {
|
||||
|
||||
/**
|
||||
* 插入属性明细
|
||||
* @param propId 属性ID
|
||||
* @param list 明细列表
|
||||
*/
|
||||
void insertDtls(@Param("propId") Long propId, @Param("list") List<ProdPropDtl> list);
|
||||
|
||||
/**
|
||||
* 按属性ID删除明细
|
||||
* @param propId 属性ID
|
||||
*/
|
||||
void deleteByPropId(@Param("propId") Long propId);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ProdProp;
|
||||
import com.ruoyi.jyshop.utils.PageAdapter;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品属性Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProdPropMapper extends BaseMapper<ProdProp> {
|
||||
|
||||
/**
|
||||
* 根据参数获取商品属性列表
|
||||
* @param adapter 分页适配器
|
||||
* @param prodProp 查询条件
|
||||
* @return 属性列表
|
||||
*/
|
||||
List<ProdProp> listPropAndValue(@Param("adapter") PageAdapter adapter, @Param("prodProp") ProdProp prodProp);
|
||||
|
||||
/**
|
||||
* 根据参数计算商品属性总数
|
||||
* @param prodProp 查询条件
|
||||
* @return 总数
|
||||
*/
|
||||
long countPropAndValue(@Param("prodProp") ProdProp prodProp);
|
||||
|
||||
/**
|
||||
* 根据主键删除商品属性
|
||||
* @param id 主键
|
||||
* @return 删除行数
|
||||
*/
|
||||
int deleteByPropId(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据属性名称获取商品属性
|
||||
* @param name 属性名称
|
||||
* @return 属性信息
|
||||
*/
|
||||
ProdProp getProdPropByName(@Param("name") String name);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品SKU Mapper接口 (shop_prod_sku)
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProdSkuMapper extends BaseMapper<ProdSku> {
|
||||
|
||||
/**
|
||||
* 批量插入sku
|
||||
* @param prodId 商品id
|
||||
* @param skuList sku列表
|
||||
*/
|
||||
void insertBatch(@Param("prodId") Long prodId, @Param("skuList") List<ProdSku> skuList);
|
||||
|
||||
/**
|
||||
* 根据商品id获取商品sku列表
|
||||
* @param prodId 商品ID
|
||||
* @return sku列表
|
||||
*/
|
||||
List<ProdSku> listByProdId(@Param("prodId") Long prodId);
|
||||
|
||||
/**
|
||||
* 更新sku库存
|
||||
* @param sku sku信息
|
||||
* @return 更新行数
|
||||
*/
|
||||
int updateStocks(@Param("sku") ProdSku sku);
|
||||
|
||||
/**
|
||||
* 根据商品id删除sku
|
||||
* @param prodId 商品ID
|
||||
*/
|
||||
void deleteByProdId(@Param("prodId") Long prodId);
|
||||
|
||||
/**
|
||||
* 返回sku库存
|
||||
* @param skuCollect skuID和数量的Map
|
||||
*/
|
||||
void returnStock(@Param("skuCollect") Map<Long, Integer> skuCollect);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ProdTag;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品-标签关联 Mapper 接口 (shop_prod_tag)
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProdTagMapper extends BaseMapper<ProdTag> {
|
||||
|
||||
/**
|
||||
* 批量插入标签
|
||||
* @param shopId 店铺ID
|
||||
* @param prodId 商品ID
|
||||
* @param tagList 标签ID列表
|
||||
*/
|
||||
void insertBatch(@Param("shopId") Long shopId, @Param("prodId") Long prodId, @Param("tagList") List<Long> tagList);
|
||||
|
||||
/**
|
||||
* 根据商品ID获取标签id列表
|
||||
* @param prodId 商品ID
|
||||
* @return 标签ID列表
|
||||
*/
|
||||
List<Long> listTagIdByProdId(@Param("prodId") Long prodId);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.Product;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ProductMapper extends BaseMapper<Product> {
|
||||
|
||||
/**
|
||||
* 更新商品库存
|
||||
* @param product 商品信息
|
||||
* @return 更新行数
|
||||
*/
|
||||
int updateStocks(@Param("prod") Product product);
|
||||
|
||||
/**
|
||||
* 返回库存
|
||||
* @param prodCollect 商品ID和数量的Map
|
||||
*/
|
||||
void returnStock(@Param("prodCollect") Map<Long, Integer> prodCollect);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplateFreeDtl;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板包邮区域明细 Mapper
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShippingTemplateFreeDtlMapper extends BaseMapper<ShippingTemplateFreeDtl> {
|
||||
|
||||
void insertDtls(@Param("list") List<ShippingTemplateFreeDtl> list);
|
||||
|
||||
void deleteBatchByParentIds(@Param("parentIds") List<Long> parentIds);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplate;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplateFree;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板 Mapper 接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShippingTemplateMapper extends BaseMapper<ShippingTemplate> {
|
||||
|
||||
/**
|
||||
* 根据运费模板id获取计费规则和包邮规则
|
||||
*/
|
||||
ShippingTemplate getTemplateAndAllItems(@Param("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据id批量删除
|
||||
*/
|
||||
void deleteByIds(@Param("ids") Long[] ids);
|
||||
|
||||
/**
|
||||
* 根据模板id获取包邮规则及区域
|
||||
*/
|
||||
List<ShippingTemplateFree> getFreeAndDtlByTemplateId(@Param("templateId") Long templateId);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplatePaidDtl;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板计费区域明细 Mapper
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShippingTemplatePaidDtlMapper extends BaseMapper<ShippingTemplatePaidDtl> {
|
||||
|
||||
void insertDtls(@Param("list") List<ShippingTemplatePaidDtl> list);
|
||||
|
||||
void deleteBatchByParentIds(@Param("parentIds") List<Long> parentIds);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplateFree;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplatePaid;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板计费规则 Mapper
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShippingTemplatePaidMapper extends BaseMapper<ShippingTemplatePaid> {
|
||||
|
||||
void insertPaids(@Param("list") List<ShippingTemplatePaid> list);
|
||||
|
||||
void insertFrees(@Param("list") List<ShippingTemplateFree> list);
|
||||
|
||||
void deleteByTemplateId(@Param("templateId") Long templateId);
|
||||
|
||||
void deleteFreesByTemplateId(@Param("templateId") Long templateId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShopInvoiceBasic;
|
||||
|
||||
/**
|
||||
* 发票基本信息 Mapper
|
||||
*/
|
||||
public interface ShopInvoiceBasicMapper extends BaseMapper<ShopInvoiceBasic> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderFundFlow;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单资金流水 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShopOrderFundFlowMapper extends BaseMapper<ShopOrderFundFlow> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单日志 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface ShopOrderLogMapper extends BaseMapper<ShopOrderLog> {
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.jyshop.domain.UserAddr;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 用户地址Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserAddrMapper extends BaseMapper<UserAddr> {
|
||||
|
||||
/**
|
||||
* 获取用户默认地址
|
||||
* @param userId 用户ID
|
||||
* @return 用户地址信息
|
||||
*/
|
||||
UserAddr getDefaultUserAddr(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 移除用户默认地址
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void removeDefaultUserAddr(@Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 设置默认地址
|
||||
* @param addrId 地址ID
|
||||
* @param userId 用户ID
|
||||
* @return 更新行数
|
||||
*/
|
||||
int setDefaultUserAddr(@Param("addrId") Long addrId, @Param("userId") String userId);
|
||||
|
||||
/**
|
||||
* 根据用户id和地址id获取用户地址
|
||||
* @param userId 用户ID
|
||||
* @param addrId 地址ID
|
||||
* @return 用户地址信息
|
||||
*/
|
||||
UserAddr getUserAddrByUserIdAndAddrId(@Param("userId") String userId, @Param("addrId") Long addrId);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Area;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 区域Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IAreaService extends IService<Area> {
|
||||
|
||||
/**
|
||||
* 通过pid 查找地址接口
|
||||
*
|
||||
* @param pid 父id
|
||||
* @return
|
||||
*/
|
||||
List<Area> listByPid(Long pid);
|
||||
|
||||
/**
|
||||
* 通过pid 清除地址缓存
|
||||
*
|
||||
* @param pid
|
||||
*/
|
||||
void removeAreaCacheByParentId(Long pid);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.AttachFile;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 附件文件Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IAttachFileService extends IService<AttachFile> {
|
||||
|
||||
/**
|
||||
* 上传文件到本地
|
||||
* @param file 文件
|
||||
* @return 文件路径
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
String uploadFile(MultipartFile file) throws IOException;
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param fileName 文件名称
|
||||
*/
|
||||
void deleteFile(String fileName);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Basket;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 购物车Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IBasketService extends IService<Basket> {
|
||||
|
||||
/**
|
||||
* 获取购物车中拥有某件商品的用户,用于清除该用户购物车的缓存
|
||||
* @param prodId 商品id
|
||||
* @return 用户id列表
|
||||
*/
|
||||
List<String> listUserIdByProdId(Long prodId);
|
||||
|
||||
/**
|
||||
* 删除购物车缓存
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void removeShopCartItemsCacheByUserId(String userId);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Category;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface ICategoryService extends IService<Category> {
|
||||
|
||||
/**
|
||||
* 根据parentId获取分类
|
||||
* @param parentId 0 一级分类
|
||||
* @return 分类列表
|
||||
*/
|
||||
List<Category> listByParentId(Long parentId);
|
||||
|
||||
/**
|
||||
* 获取用于页面表单展现的category列表,根据seq排序
|
||||
* @param shopId 店铺id
|
||||
* @return 分类列表
|
||||
*/
|
||||
List<Category> tableCategory(Long shopId);
|
||||
|
||||
/**
|
||||
* 保存分类、品牌、参数
|
||||
* @param category 分类信息
|
||||
*/
|
||||
void saveCategory(Category category);
|
||||
|
||||
/**
|
||||
* 修改分类、品牌、参数
|
||||
* @param category 分类信息
|
||||
*/
|
||||
void updateCategory(Category category);
|
||||
|
||||
/**
|
||||
* 删除分类、品牌、参数 以及分类对应的图片
|
||||
* @param categoryId 分类id
|
||||
*/
|
||||
void deleteCategory(Long categoryId);
|
||||
|
||||
/**
|
||||
* 根据店铺id和层级,获取商品分类树
|
||||
* @param shopId 店铺ID
|
||||
* @param level 层级
|
||||
* @return 分类树
|
||||
*/
|
||||
List<Category> treeSelect(Long shopId, int level);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Delivery;
|
||||
|
||||
/**
|
||||
* 物流公司Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IDeliveryService extends IService<Delivery> {
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.InviteCode;
|
||||
|
||||
/**
|
||||
* 邀请码Service接口
|
||||
*/
|
||||
public interface IInviteCodeService extends IService<InviteCode> {
|
||||
|
||||
/**
|
||||
* 批量生成邀请码(6位字母+数字,保证不重复)
|
||||
* @param count 数量
|
||||
* @param createBy 创建人
|
||||
*/
|
||||
void generate(int count, String createBy);
|
||||
|
||||
/**
|
||||
* 校验邀请码是否可用(用于立即购买跳转前)
|
||||
* @param code 邀请码
|
||||
* @return 0-初始可用,1-已下单(未支付),2-已支付;不存在返回 null
|
||||
*/
|
||||
Integer validateForUse(String code);
|
||||
|
||||
/**
|
||||
* 提交订单时绑定邀请码:写入用户id/用户名、订单编码,状态更新为已下单(1)
|
||||
* @param code 邀请码
|
||||
* @param userId 用户ID
|
||||
* @param userName 用户名
|
||||
* @param orderNumber 订单编码
|
||||
*/
|
||||
void bindToOrder(String code, String userId, String userName, String orderNumber);
|
||||
|
||||
/**
|
||||
* 取消订单时重置邀请码:状态改为初始(0),清空用户id/用户名/订单编码
|
||||
* @param orderNumber 订单编码
|
||||
*/
|
||||
void resetByOrderNumber(String orderNumber);
|
||||
|
||||
/**
|
||||
* 支付成功后,根据订单号将邀请码状态更新为已支付(2)
|
||||
* @param orderNumber 订单编码
|
||||
*/
|
||||
void markPaidByOrderNumber(String orderNumber);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.OrderAddr;
|
||||
|
||||
/**
|
||||
* 订单地址Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IOrderAddrService extends IService<OrderAddr> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.OrderItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单项Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IOrderItemService extends IService<OrderItem> {
|
||||
|
||||
/**
|
||||
* 根据订单编号获取订单项
|
||||
* @param orderNumber 订单编号
|
||||
* @return 订单项列表
|
||||
*/
|
||||
List<OrderItem> getOrderItemsByOrderNumber(String orderNumber);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Order;
|
||||
import com.ruoyi.jyshop.vo.OrderParam;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IOrderService extends IService<Order> {
|
||||
|
||||
/**
|
||||
* 根据订单编号获取订单
|
||||
* @param orderNumber 订单编号
|
||||
* @return 订单信息
|
||||
*/
|
||||
Order getOrderByOrderNumber(String orderNumber);
|
||||
|
||||
/**
|
||||
* 发货
|
||||
* @param order 订单信息
|
||||
*/
|
||||
void delivery(Order order);
|
||||
|
||||
/**
|
||||
* 待发货订单退款(关闭订单)
|
||||
* @param orderNumber 订单编号
|
||||
*/
|
||||
void refund(String orderNumber);
|
||||
|
||||
/**
|
||||
* 用户发起仅退款:待发货(2) -> 仅退款(60)
|
||||
*/
|
||||
void applyRefundRequestByUser(String orderNumber, String userId, String operatorName);
|
||||
|
||||
/**
|
||||
* 用户申请退货退款:已收货(31) -> 退款退货(61)
|
||||
*/
|
||||
void applyReturnRefundByUser(String orderNumber, String userId, String operatorName);
|
||||
|
||||
/**
|
||||
* 用户录入退货物流:同意退货(62) -> 退货中(63),写日志含物流公司、单号
|
||||
*/
|
||||
void submitUserReturnLogistics(String orderNumber, String userId, String operatorName,
|
||||
String logisticsCompany, String logisticsNo);
|
||||
|
||||
/**
|
||||
* 商家同意退货退款:退款退货(61) -> 同意退货(62)
|
||||
*/
|
||||
void agreeReturnRefund(String orderNumber);
|
||||
|
||||
/**
|
||||
* 商家确认收到退货:退货中(63) -> 已退货(64)
|
||||
*/
|
||||
void confirmMerchantReturnReceived(String orderNumber);
|
||||
|
||||
/**
|
||||
* 管理端发起微信退款前:订单置为退款中(65)。允许 2、60、30、31、64、71(及历史申请退款 5);已为 65 则 false。
|
||||
*/
|
||||
boolean markRefundingForWechat(String orderNumber);
|
||||
|
||||
/**
|
||||
* 微信退款接口失败:退款中(65) -> 退款失败(71)
|
||||
*/
|
||||
void markRefundFailedByWechat(String orderNumber, String failReason);
|
||||
|
||||
/**
|
||||
* 用户取消订单(待付款订单置为取消状态,由调用方传入)
|
||||
* @param orderNumber 订单编号
|
||||
* @param operatorId 操作人ID(可空,如用户取消时传)
|
||||
* @param operatorName 操作人名称(可空)
|
||||
* @param cancelStatus 取消后的订单状态码
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean cancelByOrderNumber(String orderNumber, String operatorId, String operatorName, Integer cancelStatus);
|
||||
|
||||
/**
|
||||
* 系统自动关闭订单(超时未付款),仅更新订单状态,不处理邀请码
|
||||
* @param orderNumber 订单编号
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean autoCloseByOrderNumber(String orderNumber);
|
||||
|
||||
/**
|
||||
* 确认收货(待收货订单更新为状态3-完成)
|
||||
* @param orderNumber 订单编号
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean confirmReceiptByOrderNumber(String orderNumber);
|
||||
|
||||
/**
|
||||
* 根据参数获取订单列表
|
||||
* @param order 订单参数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 订单列表
|
||||
*/
|
||||
List<Order> listOrdersDetailByOrder(Order order, Date startTime, Date endTime);
|
||||
|
||||
/**
|
||||
* 根据参数分页获取订单
|
||||
* @param page 分页对象
|
||||
* @param orderParam 订单参数
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<Order> pageOrdersDetailByOrderParam(Page<Order> page, OrderParam orderParam);
|
||||
|
||||
/**
|
||||
* 待付款且已产生微信预下单的订单(用于支付模块定时向微信查单补单)
|
||||
*
|
||||
* @param limit 最大条数
|
||||
*/
|
||||
List<Order> listUnpaidWithWechatPrepay(int limit);
|
||||
|
||||
/**
|
||||
* 退款中(65)且已写入商户退款单号的订单(用于支付模块定时查询微信退款结果,补偿回调丢失)
|
||||
*/
|
||||
List<Order> listRefundingWithWechatOutRefundNo(int limit);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
/**
|
||||
* 待支付订单倒计时(Redis 10 分钟)
|
||||
*/
|
||||
public interface IOrderUnpayCountdownService {
|
||||
|
||||
/**
|
||||
* 提交订单后写入 Redis,10 分钟后过期
|
||||
* @param orderNumber 订单编号
|
||||
* @return 过期时间戳(毫秒)
|
||||
*/
|
||||
long put(String orderNumber);
|
||||
|
||||
/**
|
||||
* 移除倒计时(支付成功或用户取消时调用)
|
||||
*/
|
||||
void remove(String orderNumber);
|
||||
|
||||
/**
|
||||
* 获取订单剩余过期时间戳(毫秒),不存在返回 null
|
||||
*/
|
||||
Long getExpireAt(String orderNumber);
|
||||
|
||||
/**
|
||||
* 扫描并取消已过期的待支付订单(定时任务调用)
|
||||
*/
|
||||
void scanAndCancelExpired();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.PickAddr;
|
||||
|
||||
/**
|
||||
* 自提地址Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IPickAddrService extends IService<PickAddr> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ProdPropDtl;
|
||||
|
||||
/**
|
||||
* 商品属性明细Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IProdPropDtlService extends IService<ProdPropDtl> {
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ProdProp;
|
||||
|
||||
/**
|
||||
* 商品属性Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IProdPropService extends IService<ProdProp> {
|
||||
|
||||
/**
|
||||
* 获取属性与属性值
|
||||
* @param prodProp 查询条件
|
||||
* @param page 分页对象
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<ProdProp> pagePropAndValue(ProdProp prodProp, Page<ProdProp> page);
|
||||
|
||||
/**
|
||||
* 保存属性、属性值
|
||||
* @param prodProp 属性信息
|
||||
*/
|
||||
void saveProdPropAndValues(ProdProp prodProp);
|
||||
|
||||
/**
|
||||
* 更新属性、属性值
|
||||
* @param prodProp 属性信息
|
||||
*/
|
||||
void updateProdPropAndValues(ProdProp prodProp);
|
||||
|
||||
/**
|
||||
* 删除属性及其属性值、分类关联
|
||||
* @param propId 属性主键ID
|
||||
*/
|
||||
void deleteProdPropAndValues(Long propId);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ProdSku;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品SKU Service接口 (shop_prod_sku)
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IProdSkuService extends IService<ProdSku> {
|
||||
|
||||
List<ProdSku> listByProdId(Long prodId);
|
||||
|
||||
ProdSku getProdSkuBySkuId(Long skuId);
|
||||
|
||||
void removeSkuCacheBySkuId(Long skuId, Long prodId);
|
||||
|
||||
void evictSkuListCache(Long prodId);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ProdTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品-标签关联 Service 接口 (shop_prod_tag)
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IProdTagService extends IService<ProdTag> {
|
||||
|
||||
/**
|
||||
* 根据商品ID获取标签id列表
|
||||
* @param prodId 商品ID
|
||||
* @return 标签ID列表
|
||||
*/
|
||||
List<Long> listTagIdByProdId(Long prodId);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.Product;
|
||||
|
||||
/**
|
||||
* 商品Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IProductService extends IService<Product> {
|
||||
|
||||
/**
|
||||
* 保存商品
|
||||
* @param product 商品信息
|
||||
*/
|
||||
void saveProduct(Product product);
|
||||
|
||||
/**
|
||||
* 更新商品
|
||||
* @param product 商品信息
|
||||
* @param dbProduct 数据库中的商品信息
|
||||
*/
|
||||
void updateProduct(Product product, Product dbProduct);
|
||||
|
||||
/**
|
||||
* 根据商品id获取商品信息
|
||||
* @param prodId 商品ID
|
||||
* @return 商品信息
|
||||
*/
|
||||
Product getProductByProdId(Long prodId);
|
||||
|
||||
/**
|
||||
* 根据商品id删除商品
|
||||
* @param prodId 商品ID
|
||||
*/
|
||||
void removeProductByProdId(Long prodId);
|
||||
|
||||
/**
|
||||
* 根据商品id删除缓存
|
||||
* @param prodId 商品ID
|
||||
*/
|
||||
void removeProductCacheByProdId(Long prodId);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ShippingTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 运费模板 Service 接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-27
|
||||
*/
|
||||
public interface IShippingTemplateService extends IService<ShippingTemplate> {
|
||||
|
||||
void insertTemplateAndRules(ShippingTemplate template);
|
||||
|
||||
void updateTemplateAndRules(ShippingTemplate template);
|
||||
|
||||
void deleteTemplateAndRules(Long[] ids);
|
||||
|
||||
ShippingTemplate getTemplateAndAllItems(Long templateId);
|
||||
|
||||
void removeTemplateCache(Long templateId);
|
||||
|
||||
double calculateTransfee(Long templateId, List<Long> userAreaIds, double totalAmount, int totalCount, double totalWeight, double totalVolume);
|
||||
|
||||
Long getFirstTemplateIdByShopId(Long shopId);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ShopInvoiceBasic;
|
||||
import com.ruoyi.jyshop.vo.InvoiceRecognizeResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 发票基本信息 Service
|
||||
*/
|
||||
public interface IShopInvoiceBasicService extends IService<ShopInvoiceBasic> {
|
||||
|
||||
IPage<ShopInvoiceBasic> pageList(Page<ShopInvoiceBasic> page, ShopInvoiceBasic query);
|
||||
|
||||
InvoiceRecognizeResult recognizeAndSave(MultipartFile file, String username) throws IOException;
|
||||
|
||||
/**
|
||||
* 手动录入发票号码(仅号码,同一号码不可重复)
|
||||
*/
|
||||
ShopInvoiceBasic saveManualInvoiceNumber(String invoiceNumber, String username);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.jyshop.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.jyshop.domain.ShopOrderFundFlow;
|
||||
|
||||
/**
|
||||
* 订单资金流水 Service
|
||||
*/
|
||||
public interface IShopOrderFundFlowService extends IService<ShopOrderFundFlow> {
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user