Merge pull request 'wangjinhao' (#3) from wangjinhao_branch into develop

develop
方建军 9 months ago
commit 988cf84554

@ -0,0 +1 @@
undefined

@ -0,0 +1,143 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import cn.hutool.core.util.StrUtil; // 引入Hutool工具类库中的StrUtil工具类用于字符串操作
import com.anji.captcha.model.common.ResponseModel; // 引入验证码响应模型
import com.anji.captcha.model.vo.CaptchaVO; // 引入验证码模型
import com.anji.captcha.service.CaptchaService; // 引入验证码服务
import com.baomidou.mybatisplus.core.toolkit.Wrappers; // 引入MyBatis-Plus工具类Wrappers
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import com.yami.shop.security.admin.dto.CaptchaAuthenticationDTO; // 引入验证码认证DTO
import com.yami.shop.security.common.bo.UserInfoInTokenBO; // 引入用户信息类
import com.yami.shop.security.common.enums.SysTypeEnum; // 引入系统类型枚举
import com.yami.shop.security.common.manager.PasswordCheckManager; // 引入密码校验管理类
import com.yami.shop.security.common.manager.PasswordManager; // 引入密码管理类
import com.yami.shop.security.common.manager.TokenStore; // 引入Token存储管理类
import com.yami.shop.security.common.vo.TokenInfoVO; // 引入Token信息VO
import com.yami.shop.sys.constant.Constant; // 引入系统常量
import com.yami.shop.sys.model.SysMenu; // 引入系统菜单模型
import com.yami.shop.sys.model.SysUser; // 引入系统用户模型
import com.yami.shop.sys.service.SysMenuService; // 引入系统菜单服务
import com.yami.shop.sys.service.SysUserService; // 引入系统用户服务
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import org.springframework.web.bind.annotation.PostMapping; // 引入Spring的@PostMapping注解
import org.springframework.web.bind.annotation.RequestBody; // 引入Spring的@RequestBody注解
import org.springframework.web.bind.annotation.RestController; // 引入Spring的@RestController注解
import jakarta.validation.Valid; // 引入Jakarta Validation的Valid注解
import java.util.Arrays; // 引入Java的Arrays工具类
import java.util.List; // 引入Java的List接口
import java.util.Objects; // 引入Java的Objects工具类
import java.util.Set; // 引入Java的Set接口
import java.util.stream.Collectors; // 引入Java的Collectors工具类
/**
* AdminLoginController
*
* //Token
* @ FrozenWatermelon
* @ 2020/6/30
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@Tag(name = "登录") // 给API文档添加标签描述这个控制器的功能
public class AdminLoginController {
@Autowired
private TokenStore tokenStore; // 自动注入Token存储管理类
@Autowired
private SysUserService sysUserService; // 自动注入系统用户服务
@Autowired
private SysMenuService sysMenuService; // 自动注入系统菜单服务
@Autowired
private PasswordCheckManager passwordCheckManager; // 自动注入密码校验管理类
@Autowired
private CaptchaService captchaService; // 自动注入验证码服务
@Autowired
private PasswordManager passwordManager; // 自动注入密码管理类
/**
* + ()
* //
* @param captchaAuthenticationDTO DTO
* @return Token
*/
@PostMapping("/adminLogin")
@Operation(summary = "账号密码 + 验证码登录(用于后台登录)" , description = "通过账号/手机号/用户名密码登录")
public ServerResponseEntity<?> login(
@Valid @RequestBody CaptchaAuthenticationDTO captchaAuthenticationDTO) {
// 登陆后台登录需要再校验一遍验证码
CaptchaVO captchaVO = new CaptchaVO();
captchaVO.setCaptchaVerification(captchaAuthenticationDTO.getCaptchaVerification());
ResponseModel response = captchaService.verification(captchaVO);
if (!response.isSuccess()) {
return ServerResponseEntity.showFailMsg("验证码有误或已过期");
}
SysUser sysUser = sysUserService.getByUserName(captchaAuthenticationDTO.getUserName());
if (sysUser == null) {
throw new YamiShopBindException("账号或密码不正确");
}
// 半小时内密码输入错误十次已限制登录30分钟
String decryptPassword = passwordManager.decryptPassword(captchaAuthenticationDTO.getPassWord());
passwordCheckManager.checkPassword(SysTypeEnum.ADMIN, captchaAuthenticationDTO.getUserName(), decryptPassword, sysUser.getPassword());
// 不是店铺超级管理员,并且是禁用状态,无法登录
if (Objects.equals(sysUser.getStatus(), 0)) {
// 未找到此用户信息
throw new YamiShopBindException("未找到此用户信息");
}
UserInfoInTokenBO userInfoInToken = new UserInfoInTokenBO();
userInfoInToken.setUserId(String.valueOf(sysUser.getUserId()));
userInfoInToken.setSysType(SysTypeEnum.ADMIN.value());
userInfoInToken.setEnabled(sysUser.getStatus() == 1);
userInfoInToken.setPerms(getUserPermissions(sysUser.getUserId()));
userInfoInToken.setNickName(sysUser.getUsername());
userInfoInToken.setShopId(sysUser.getShopId());
// 存储token返回vo
TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
return ServerResponseEntity.success(tokenInfoVO);
}
/**
*
* ID
* @param userId ID
* @return Set
*/
private Set<String> getUserPermissions(Long userId) {
List<String> permsList;
//系统管理员,拥有最高权限
if(userId == Constant.SUPER_ADMIN_ID){
List<SysMenu> menuList = sysMenuService.list(Wrappers.emptyWrapper());
permsList = menuList.stream().map(SysMenu::getPerms).collect(Collectors.toList());
}else{
permsList = sysUserService.queryAllPerms(userId);
}
return permsList.stream().flatMap((perms) -> {
if (StrUtil.isBlank(perms)) {
return null;
}
return Arrays.stream(perms.trim().split(StrUtil.COMMA));
}
).collect(Collectors.toSet());
}
}

@ -0,0 +1,157 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 引入MyBatis-Plus的条件查询包装器
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.yami.shop.bean.enums.AreaLevelEnum; // 引入区域级别枚举
import com.yami.shop.bean.model.Area; // 引入区域模型
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.service.AreaService; // 引入区域服务类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid; // 引入Jakarta Validation的Valid注解
import java.util.List; // 引入Java的List接口
import java.util.Objects; // 引入Java的Objects工具类
/**
* AreaController
* ID
* @ lgh on 2018/10/26.
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/admin/area") // 定义请求路径的根地址为/admin/area
public class AreaController {
@Autowired
private AreaService areaService; // 自动注入区域服务类
/**
*
* @param area
* @param page
* @return
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin:area:page')") // 权限检查
public ServerResponseEntity<IPage<Area>> page(Area area, PageParam<Area> page) {
IPage<Area> areaPage = areaService.page(page, new LambdaQueryWrapper<Area>());
return ServerResponseEntity.success(areaPage);
}
/**
*
* @param area
* @return
*/
@GetMapping("/list")
@PreAuthorize("@pms.hasPermission('admin:area:list')") // 权限检查
public ServerResponseEntity<List<Area>> list(Area area) {
List<Area> areas = areaService.list(new LambdaQueryWrapper<Area>()
.like(area.getAreaName() != null, Area::getAreaName, area.getAreaName()));
return ServerResponseEntity.success(areas);
}
/**
* ID
* @param pid ID
* @return
*/
@GetMapping("/listByPid")
public ServerResponseEntity<List<Area>> listByPid(Long pid) {
List<Area> list = areaService.listByPid(pid);
return ServerResponseEntity.success(list);
}
/**
*
* @param id ID
* @return
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('admin:area:info')") // 权限检查
public ServerResponseEntity<Area> info(@PathVariable("id") Long id) {
Area area = areaService.getById(id);
return ServerResponseEntity.success(area);
}
/**
*
* @param area
* @return
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('admin:area:save')") // 权限检查
public ServerResponseEntity<Void> save(@Valid @RequestBody Area area) {
if (area.getParentId() != null) {
Area parentArea = areaService.getById(area.getParentId());
area.setLevel(parentArea.getLevel() + 1);
areaService.removeAreaCacheByParentId(area.getParentId());
}
areaService.save(area);
return ServerResponseEntity.success();
}
/**
*
* @param area
* @return
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('admin:area:update')") // 权限检查
public ServerResponseEntity<Void> update(@Valid @RequestBody Area area) {
Area areaDb = areaService.getById(area.getAreaId());
// 判断当前省市区级别如果是1级、2级则不能修改级别不能修改成别人的下级
if(Objects.equals(areaDb.getLevel(), AreaLevelEnum.FIRST_LEVEL.value()) && !Objects.equals(area.getLevel(), AreaLevelEnum.FIRST_LEVEL.value())){
throw new YamiShopBindException("不能改变一级行政地区的级别");
}
if(Objects.equals(areaDb.getLevel(), AreaLevelEnum.SECOND_LEVEL.value()) && !Objects.equals(area.getLevel(), AreaLevelEnum.SECOND_LEVEL.value())){
throw new YamiShopBindException("不能改变二级行政地区的级别");
}
hasSameName(area);
areaService.updateById(area);
areaService.removeAreaCacheByParentId(area.getParentId());
return ServerResponseEntity.success();
}
/**
*
* @param id ID
* @return
*/
@DeleteMapping("/{id}")
@PreAuthorize("@pms.hasPermission('admin:area:delete')") // 权限检查
public ServerResponseEntity<Void> delete(@PathVariable Long id) {
Area area = areaService.getById(id);
areaService.removeById(id);
areaService.removeAreaCacheByParentId(area.getParentId());
return ServerResponseEntity.success();
}
/**
*
* @param area
*/
private void hasSameName(Area area) {
long count = areaService.count(new LambdaQueryWrapper<Area>()
.eq(Area::getParentId, area.getParentId())
.eq(Area::getAreaName, area.getAreaName())
.ne(Objects.nonNull(area.getAreaId()) && !Objects.equals(area.getAreaId(), 0L), Area::getAreaId, area.getAreaId())
);
if (count > 0) {
throw new YamiShopBindException("该地区已存在");
}
}
}

@ -0,0 +1,150 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 引入MyBatis-Plus的条件查询包装器
import com.yami.shop.bean.model.Category; // 引入商品分类模型类
import com.yami.shop.common.annotation.SysLog; // 引入自定义日志注解
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.security.admin.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.CategoryService; // 引入商品分类服务类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*;
import java.util.Date; // 引入Java的Date类
import java.util.List; // 引入Java的List接口
import java.util.Objects; // 引入Java的Objects工具类
/**
*
*
* @ lgh
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/prod/category") // 定义请求路径的根地址为/prod/category
public class CategoryController {
@Autowired
private CategoryService categoryService; // 自动注入商品分类服务类
/**
*
* @return
*/
@GetMapping("/table")
@PreAuthorize("@pms.hasPermission('prod:category:page')") // 权限检查
public ServerResponseEntity<List<Category>> table() {
List<Category> categoryMenuList = categoryService.tableCategory(SecurityUtils.getSysUser().getShopId());
return ServerResponseEntity.success(categoryMenuList);
}
/**
*
* @param categoryId ID
* @return
*/
@GetMapping("/info/{categoryId}")
public ServerResponseEntity<Category> info(@PathVariable("categoryId") Long categoryId) {
Category category = categoryService.getById(categoryId);
return ServerResponseEntity.success(category);
}
/**
*
* @param category
* @return
*/
@SysLog("保存分类") // 自定义日志注解
@PostMapping
@PreAuthorize("@pms.hasPermission('prod:category:save')") // 权限检查
public ServerResponseEntity<Void> save(@RequestBody Category category) {
category.setShopId(SecurityUtils.getSysUser().getShopId());
category.setRecTime(new Date());
Category categoryName = categoryService.getOne(new LambdaQueryWrapper<Category>().eq(Category::getCategoryName, category.getCategoryName())
.eq(Category::getShopId, category.getShopId()));
if (Objects.nonNull(categoryName)) {
throw new YamiShopBindException("类目名称已存在!");
}
categoryService.saveCategory(category);
return ServerResponseEntity.success();
}
/**
*
* @param category
* @return
*/
@SysLog("更新分类") // 自定义日志注解
@PutMapping
@PreAuthorize("@pms.hasPermission('prod:category:update')") // 权限检查
public ServerResponseEntity<String> update(@RequestBody Category category) {
category.setShopId(SecurityUtils.getSysUser().getShopId());
if (Objects.equals(category.getParentId(), category.getCategoryId())) {
return ServerResponseEntity.showFailMsg("分类的上级不能是自己本身");
}
Category categoryName = categoryService.getOne(new LambdaQueryWrapper<Category>().eq(Category::getCategoryName, category.getCategoryName())
.eq(Category::getShopId, category.getShopId()).ne(Category::getCategoryId, category.getCategoryId()));
if (categoryName != null) {
throw new YamiShopBindException("类目名称已存在!");
}
Category categoryDb = categoryService.getById(category.getCategoryId());
// 如果从下线改成正常,则需要判断上级的状态
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::getCategoryId, category.getParentId()));
if (Objects.isNull(parentCategory) || Objects.equals(parentCategory.getStatus(), 0)) {
// 修改失败,上级分类不存在或者不为正常状态
throw new YamiShopBindException("修改失败,上级分类不存在或者不为正常状态");
}
}
categoryService.updateCategory(category);
return ServerResponseEntity.success();
}
/**
*
* @param categoryId ID
* @return
*/
@SysLog("删除分类") // 自定义日志注解
@DeleteMapping("/{categoryId}")
@PreAuthorize("@pms.hasPermission('prod:category:delete')") // 权限检查
public ServerResponseEntity<String> delete(@PathVariable("categoryId") Long categoryId) {
if (categoryService.count(new LambdaQueryWrapper<Category>().eq(Category::getParentId, categoryId)) > 0) {
return ServerResponseEntity.showFailMsg("请删除子分类,再删除该分类");
}
categoryService.deleteCategory(categoryId);
return ServerResponseEntity.success();
}
/**
*
* @return
*/
@GetMapping("/listCategory")
public ServerResponseEntity<List<Category>> listCategory() {
return ServerResponseEntity.success(categoryService.list(new LambdaQueryWrapper<Category>()
.le(Category::getGrade, 2)
.eq(Category::getShopId, SecurityUtils.getSysUser().getShopId())
.orderByAsc(Category::getSeq)));
}
/**
*
* @return
*/
@GetMapping("/listProdCategory")
public ServerResponseEntity<List<Category>> listProdCategory() {
List<Category> categories = categoryService.treeSelect(SecurityUtils.getSysUser().getShopId(), 2);
return ServerResponseEntity.success(categories);
}
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import java.util.List; // 引入Java的List接口
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.GetMapping; // 引入Spring的@GetMapping注解
import org.springframework.web.bind.annotation.RequestMapping; // 引入Spring的@RequestMapping注解
import org.springframework.web.bind.annotation.RestController; // 引入Spring的@RestController注解
import com.yami.shop.bean.model.Delivery; // 引入配送模型
import com.yami.shop.service.DeliveryService; // 引入配送服务类
/**
* DeliveryController
*
* @ lgh on 2018/11/26.
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/admin/delivery") // 定义请求路径的根地址为/admin/delivery
public class DeliveryController {
@Autowired
private DeliveryService deliveryService; // 自动注入配送服务类
/**
*
* @return
*/
@GetMapping("/list")
public ServerResponseEntity<List<Delivery>> page() {
List<Delivery> list = deliveryService.list(); // 获取所有配送信息
return ServerResponseEntity.success(list); // 返回配送信息列表
}
}

@ -0,0 +1,309 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import cn.hutool.core.date.DatePattern; // 引入Hutool工具类库中的日期格式化工具类
import cn.hutool.core.date.DateUtil; // 引入Hutool工具类库中的日期工具类
import cn.hutool.core.io.IORuntimeException; // 引入Hutool工具类库中的IO运行时异常类
import cn.hutool.core.io.IoUtil; // 引入Hutool工具类库中的IO工具类
import cn.hutool.poi.excel.ExcelUtil; // 引入Hutool工具类库中的Excel工具类
import cn.hutool.poi.excel.ExcelWriter; // 引入Hutool工具类库中的Excel写入工具类
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.google.common.base.Objects; // 引入Google Guava库中的Objects工具类
import com.yami.shop.bean.enums.OrderStatus; // 引入订单状态枚举类
import com.yami.shop.bean.model.Order; // 引入订单模型类
import com.yami.shop.bean.model.OrderItem; // 引入订单项模型类
import com.yami.shop.bean.model.UserAddrOrder; // 引入用户地址订单模型类
import com.yami.shop.bean.param.DeliveryOrderParam; // 引入发货订单参数类
import com.yami.shop.bean.param.OrderParam; // 引入订单参数类
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.security.admin.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.*; // 引入各种服务类
import jakarta.servlet.ServletOutputStream; // 引入Servlet输出流类
import jakarta.servlet.http.HttpServletResponse; // 引入HTTP响应类
import lombok.extern.slf4j.Slf4j; // 引入Lombok的日志记录注解
import org.apache.poi.ss.usermodel.Sheet; // 引入Apache POI的Sheet类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import org.springframework.format.annotation.DateTimeFormat; // 引入Spring的日期时间格式化注解
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*; // 引入Spring Web的注解
import java.io.IOException; // 引入Java的IO异常类
import java.util.Arrays; // 引入Java的Arrays工具类
import java.util.Date; // 引入Java的Date类
import java.util.List; // 引入Java的List接口
/**
* OrderController
* @ lgh on 2018/09/15.
*/
@Slf4j // 标注这是一个需要日志记录的类
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/order/order") // 定义请求路径的根地址为/order/order
public class OrderController {
@Autowired
private OrderService orderService; // 自动注入订单服务类
@Autowired
private OrderItemService orderItemService; // 自动注入订单项服务类
@Autowired
private UserAddrOrderService userAddrOrderService; // 自动注入用户地址订单服务类
@Autowired
private ProductService productService; // 自动注入商品服务类
@Autowired
private SkuService skuService; // 自动注入SKU服务类
/**
*
* @param orderParam
* @param page
* @return
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('order:order:page')") // 权限检查
public ServerResponseEntity<IPage<Order>> page(OrderParam orderParam, PageParam<Order> page) {
Long shopId = SecurityUtils.getSysUser().getShopId();
orderParam.setShopId(shopId);
IPage<Order> orderPage = orderService.pageOrdersDetailByOrderParam(page, orderParam);
return ServerResponseEntity.success(orderPage); // 返回分页结果
}
/**
*
* @param orderNumber
* @return
*/
@GetMapping("/orderInfo/{orderNumber}")
@PreAuthorize("@pms.hasPermission('order:order:info')") // 权限检查
public ServerResponseEntity<Order> info(@PathVariable("orderNumber") String orderNumber) {
Long shopId = SecurityUtils.getSysUser().getShopId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equal(shopId, order.getShopId())) {
throw new YamiShopBindException("您没有权限获取该订单信息");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
order.setUserAddrOrder(userAddrOrder);
return ServerResponseEntity.success(order);
}
/**
*
* @param deliveryOrderParam
* @return
*/
@PutMapping("/delivery")
@PreAuthorize("@pms.hasPermission('order:order:delivery')") // 权限检查
public ServerResponseEntity<Void> delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) {
Long shopId = SecurityUtils.getSysUser().getShopId();
Order order = orderService.getOrderByOrderNumber(deliveryOrderParam.getOrderNumber());
if (!Objects.equal(shopId, order.getShopId())) {
throw new YamiShopBindException("您没有权限修改该订单信息");
}
Order orderParam = new Order();
orderParam.setOrderId(order.getOrderId());
orderParam.setDvyId(deliveryOrderParam.getDvyId());
orderParam.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
orderParam.setDvyTime(new Date());
orderParam.setStatus(OrderStatus.CONSIGNMENT.value());
orderParam.setUserId(order.getUserId());
orderService.delivery(orderParam);
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(deliveryOrderParam.getOrderNumber());
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
}
return ServerResponseEntity.success();
}
/**
*
* @param order
* @param consignmentName
* @param consignmentMobile
* @param consignmentAddr
* @param startTime
* @param endTime
* @param response HTTP
*/
* @param order
* @param startTime
* @param endTime
* @param response HTTP
*/
@GetMapping("/waitingConsignmentExcel")
@PreAuthorize("@pms.hasPermission('order:order: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 = SecurityUtils.getSysUser().getShopId();
order.setShopId(shopId);
order.setStatus(OrderStatus.PADYED.value());
List<Order> orders = orderService.listOrdersDetailByOrder(order, startTime, endTime);
// 通过工具类创建ExcelWriter
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[] hearder = {"订单编号", "收件人", "手机", "收货地址", "商品名称", "数量", "发件人姓名", "发件人手机号", "发货地址", "备注"};
writer.merge(hearder.length - 1, "发货信息整理");
writer.writeRow(Arrays.asList(hearder));
int row = 1;
for (Order dbOrder : orders) {
UserAddrOrder addr = dbOrder.getUserAddrOrder();
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
List<OrderItem> orderItems = dbOrder.getOrderItems();
row++;
for (OrderItem orderItem : orderItems) {
// 第0列开始
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.getProdCount());
writer.writeCellValue(col++, row, consignmentName);
writer.writeCellValue(col++, row, consignmentMobile);
writer.writeCellValue(col++, row, consignmentAddr);
writer.writeCellValue(col++, row, dbOrder.getRemarks());
}
}
writeExcel(response, writer);
}
/**
*
* @param order
* @param startTime
* @param endTime
* @param response HTTP
*/
@GetMapping("/soldExcel")
@PreAuthorize("@pms.hasPermission('order:order: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 = SecurityUtils.getSysUser().getShopId();
order.setShopId(shopId);
order.setIsPayed(1);
List<Order> orders = orderService.listOrdersDetailByOrder(order, startTime, endTime);
// 通过工具类创建ExcelWriter
ExcelWriter writer = ExcelUtil.getBigWriter();
String[] hearder = {"订单编号", "下单时间", "收件人", "手机", "收货地址", "商品名称", "数量", "订单应付", "订单运费", "订单实付"};
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(hearder.length - 1, "销售信息整理");
writer.writeRow(Arrays.asList(hearder));
int row = 1;
for (Order dbOrder : orders) {
UserAddrOrder addr = dbOrder.getUserAddrOrder();
String addrInfo = addr.getProvince() + addr.getCity() + addr.getArea() + addr.getAddr();
List<OrderItem> orderItems = dbOrder.getOrderItems();
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.getProdCount());
}
// 订单应付
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getTotal());
// 订单运费
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getFreightAmount());
// 订单实付
mergeIfNeed(writer, firstRow, lastRow, ++col, col, dbOrder.getActualTotal());
}
writeExcel(response, writer);
}
/**
*
* @param writer ExcelWriter
* @param firstRow
* @param lastRow
* @param firstColumn
* @param lastColumn
* @param content
*/
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);
}
}
/**
* Excel
* @param response HTTP
* @param writer ExcelWriter
*/
private void writeExcel(HttpServletResponse response, ExcelWriter writer) {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=1.xls");
ServletOutputStream servletOutputStream = null;
try {
servletOutputStream = response.getOutputStream();
writer.flush(servletOutputStream);
servletOutputStream.flush();
} catch (IORuntimeException | IOException e) {
log.error("写出Excel错误", e);
} finally {
IoUtil.close(writer);
}
}
}

@ -0,0 +1,111 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import cn.hutool.core.util.StrUtil; // 引入Hutool工具类库中的StrUtil工具类
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 引入MyBatis-Plus的条件查询包装器
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.yami.shop.bean.model.PickAddr; // 引入自提点地址模型类
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.response.ResponseEnum; // 引入响应枚举类
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.security.admin.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.PickAddrService; // 引入自提点地址服务类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*; // 引入Spring Web的注解
import jakarta.validation.Valid; // 引入Jakarta Validation的Valid注解
import java.util.Arrays; // 引入Java的Arrays工具类
import java.util.Objects; // 引入Java的Objects工具类
/**
* PickAddrController
*
* @ lgh on 2018/10/17.
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/shop/pickAddr") // 定义请求路径的根地址为/shop/pickAddr
public class PickAddrController {
@Autowired
private PickAddrService pickAddrService; // 自动注入自提点地址服务类
/**
*
* @param pickAddr
* @param page
* @return
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('shop:pickAddr:page')") // 权限检查
public ServerResponseEntity<IPage<PickAddr>> page(PickAddr pickAddr, PageParam<PickAddr> page) {
IPage<PickAddr> pickAddrs = pickAddrService.page(page, new LambdaQueryWrapper<PickAddr>()
.like(StrUtil.isNotBlank(pickAddr.getAddrName()), PickAddr::getAddrName, pickAddr.getAddrName())
.orderByDesc(PickAddr::getAddrId));
return ServerResponseEntity.success(pickAddrs); // 返回分页结果
}
/**
*
* @param id ID
* @return
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('shop:pickAddr:info')") // 权限检查
public ServerResponseEntity<PickAddr> info(@PathVariable("id") Long id) {
PickAddr pickAddr = pickAddrService.getById(id);
return ServerResponseEntity.success(pickAddr); // 返回自提点地址信息
}
/**
*
* @param pickAddr
* @return
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:save')") // 权限检查
public ServerResponseEntity<Void> save(@Valid @RequestBody PickAddr pickAddr) {
pickAddr.setShopId(SecurityUtils.getSysUser().getShopId()); // 设置店铺ID
pickAddrService.save(pickAddr); // 保存自提点地址
return ServerResponseEntity.success(); // 返回成功响应
}
/**
*
* @param pickAddr
* @return
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:update')") // 权限检查
public ServerResponseEntity<Void> update(@Valid @RequestBody PickAddr pickAddr) {
PickAddr dbPickAddr = pickAddrService.getById(pickAddr.getAddrId());
if (!Objects.equals(dbPickAddr.getShopId(), SecurityUtils.getSysUser().getShopId())) {
throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
}
pickAddrService.updateById(pickAddr); // 修改自提点地址
return ServerResponseEntity.success(); // 返回成功响应
}
/**
*
* @param ids ID
* @return
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('shop:pickAddr:delete')") // 权限检查
public ServerResponseEntity<Void> delete(@RequestBody Long[] ids) {
pickAddrService.removeByIds(Arrays.asList(ids)); // 删除自提点地址
return ServerResponseEntity.success(); // 返回成功响应
}
}

@ -0,0 +1,123 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 引入MyBatis-Plus的条件查询包装器
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.yami.shop.bean.model.Transport; // 引入运费模板模型类
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.security.admin.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.TransportService; // 引入运费模板服务类
import org.apache.commons.lang3.StringUtils; // 引入Apache Commons的StringUtils工具类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*;
import java.util.Date; // 引入Java的Date类
import java.util.List; // 引入Java的List接口
/**
*
*
* @ lgh on 2018/11/16.
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/shop/transport") // 定义请求路径的根地址为/shop/transport
public class TransportController {
@Autowired
private TransportService transportService; // 自动注入运费模板服务类
/**
*
* @param transport
* @param page
* @return
*/
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('shop:transport:page')") // 权限检查
public ServerResponseEntity<IPage<Transport>> page(Transport transport, PageParam<Transport> page) {
Long shopId = SecurityUtils.getSysUser().getShopId();
IPage<Transport> transports = transportService.page(page,
new LambdaQueryWrapper<Transport>()
.eq(Transport::getShopId, shopId)
.like(StringUtils.isNotBlank(transport.getTransName()), Transport::getTransName, transport.getTransName()));
return ServerResponseEntity.success(transports);
}
/**
*
* @param id ID
* @return
*/
@GetMapping("/info/{id}")
@PreAuthorize("@pms.hasPermission('shop:transport:info')") // 权限检查
public ServerResponseEntity<Transport> info(@PathVariable("id") Long id) {
Transport transport = transportService.getTransportAndAllItems(id);
return ServerResponseEntity.success(transport);
}
/**
*
* @param transport
* @return
*/
@PostMapping
@PreAuthorize("@pms.hasPermission('shop:transport:save')") // 权限检查
public ServerResponseEntity<Void> save(@RequestBody Transport transport) {
Long shopId = SecurityUtils.getSysUser().getShopId();
transport.setShopId(shopId);
Date createTime = new Date();
transport.setCreateTime(createTime);
transportService.insertTransportAndTransfee(transport);
return ServerResponseEntity.success();
}
/**
*
* @param transport
* @return
*/
@PutMapping
@PreAuthorize("@pms.hasPermission('shop:transport:update')") // 权限检查
public ServerResponseEntity<Void> update(@RequestBody Transport transport) {
transportService.updateTransportAndTransfee(transport);
return ServerResponseEntity.success();
}
/**
*
* @param ids ID
* @return
*/
@DeleteMapping
@PreAuthorize("@pms.hasPermission('shop:transport:delete')") // 权限检查
public ServerResponseEntity<Void> delete(@RequestBody Long[] ids) {
transportService.deleteTransportAndTransfeeAndTranscity(ids);
// 删除运费模板的缓存
for (Long id : ids) {
transportService.removeTransportAndAllItemsCache(id);
}
return ServerResponseEntity.success();
}
/**
*
* @return
*/
@GetMapping("/list")
public ServerResponseEntity<List<Transport>> list() {
Long shopId = SecurityUtils.getSysUser().getShopId();
List<Transport> list = transportService.list(new LambdaQueryWrapper<Transport>().eq(Transport::getShopId, shopId));
return ServerResponseEntity.success(list);
}
}

@ -0,0 +1,95 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.controller; // 定义类所在的包
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; // 引入MyBatis-Plus的条件查询包装器
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.bean.model.UserAddr; // 引入用户地址模型类
import com.yami.shop.common.annotation.SysLog; // 引入自定义日志注解
import com.yami.shop.service.UserAddrService; // 引入用户地址服务类
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.security.access.prepost.PreAuthorize; // 引入Spring Security的PreAuthorize注解
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid; // 引入Jakarta Validation的Valid注解
/**
*
*
* @ hzm
* @ 2019-04-15 10:49:40
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
@RequestMapping("/user/addr") // 定义请求路径的根地址为/user/addr
public class UserAddrController {
private final UserAddrService userAddrService; // 自动注入用户地址服务类
/**
*
* @param page
* @param userAddr
* @return
*/
@GetMapping("/page")
public ServerResponseEntity<IPage<UserAddr>> getUserAddrPage(PageParam page, UserAddr userAddr) {
return ServerResponseEntity.success(userAddrService.page(page, new LambdaQueryWrapper<UserAddr>())); // 返回分页结果
}
/**
* ID
* @param addrId ID
* @return
*/
@GetMapping("/info/{addrId}")
public ServerResponseEntity<UserAddr> getById(@PathVariable("addrId") Long addrId) {
return ServerResponseEntity.success(userAddrService.getById(addrId)); // 返回用户地址信息
}
/**
*
* @param userAddr
* @return
*/
@SysLog("新增用户地址管理") // 自定义日志注解
@PostMapping
@PreAuthorize("@pms.hasPermission('user:addr:save')") // 权限检查
public ServerResponseEntity<Boolean> save(@RequestBody @Valid UserAddr userAddr) {
return ServerResponseEntity.success(userAddrService.save(userAddr)); // 保存用户地址并返回结果
}
/**
*
* @param userAddr
* @return
*/
@SysLog("修改用户地址管理") // 自定义日志注解
@PutMapping
@PreAuthorize("@pms.hasPermission('user:addr:update')") // 权限检查
public ServerResponseEntity<Boolean> updateById(@RequestBody @Valid UserAddr userAddr) {
return ServerResponseEntity.success(userAddrService.updateById(userAddr)); // 修改用户地址并返回结果
}
/**
* ID
* @param addrId ID
* @return
*/
@SysLog("删除用户地址管理") // 自定义日志注解
@DeleteMapping("/{addrId}")
@PreAuthorize("@pms.hasPermission('user:addr:delete')") // 权限检查
public ServerResponseEntity<Boolean> removeById(@PathVariable Long addrId) {
return ServerResponseEntity.success(userAddrService.removeById(addrId)); // 删除用户地址并返回结果
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.admin.task; // 定义类所在的包
import cn.hutool.core.collection.CollectionUtil; // 引入Hutool工具类库中的CollectionUtil工具类
import cn.hutool.core.date.DateUtil; // 引入Hutool工具类库中的DateUtil工具类
import com.xxl.job.core.handler.annotation.XxlJob; // 引入XXL-Job的注解
import com.yami.shop.bean.enums.OrderStatus; // 引入订单状态枚举类
import com.yami.shop.bean.model.Order; // 引入订单模型类
import com.yami.shop.bean.model.OrderItem; // 引入订单项模型类
import com.yami.shop.service.OrderService; // 引入订单服务类
import com.yami.shop.service.ProductService; // 引入商品服务类
import com.yami.shop.service.SkuService; // 引入SKU服务类
import org.slf4j.Logger; // 引入SLF4J的Logger类
import org.slf4j.LoggerFactory; // 引入SLF4J的LoggerFactory类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import org.springframework.stereotype.Component; // 引入Spring的@Component注解
import java.util.Date; // 引入Java的Date类
import java.util.List; // 引入Java的List接口
/**
* OrderTask
* xxl-jobjava
* @ FrozenWatermelon
* @ com.yami.shop.admin.config.XxlJobConfig
*/
@Component("orderTask") // 标注这是一个Spring组件并且以orderTask为组件名称
public class OrderTask {
private static final Logger logger = LoggerFactory.getLogger(OrderTask.class); // 日志记录器
@Autowired
private OrderService orderService; // 自动注入订单服务类
@Autowired
private ProductService productService; // 自动注入商品服务类
@Autowired
private SkuService skuService; // 自动注入SKU服务类
/**
*
*/
@XxlJob("cancelOrder")
public void cancelOrder() {
Date now = new Date();
logger.info("取消超时未支付订单。。。");
// 获取30分钟之前未支付的订单
List<Order> orders = orderService.listOrderAndOrderItems(OrderStatus.UNPAY.value(), DateUtil.offsetMinute(now, -30));
if (CollectionUtil.isEmpty(orders)) {
return;
}
orderService.cancelOrders(orders);
for (Order order : orders) {
List<OrderItem> orderItems = order.getOrderItems();
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
}
}
}
/**
*
*/
@XxlJob("confirmOrder")
public void confirmOrder() {
Date now = new Date();
logger.info("系统自动确认收货订单。。。");
// 获取15天之前未支付的订单
List<Order> orders = orderService.listOrderAndOrderItems(OrderStatus.CONSIGNMENT.value(), DateUtil.offsetDay(now, -15));
if (CollectionUtil.isEmpty(orders)) {
return;
}
orderService.confirmOrder(orders);
for (Order order : orders) {
List<OrderItem> orderItems = order.getOrderItems();
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
}
}
}
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.config; // 定义类所在的包
import cn.hutool.core.lang.Snowflake; // 引入Hutool工具包中的Snowflake类用于生成唯一ID
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解自动生成全参构造函数
import org.springframework.context.annotation.Bean; // 引入Spring的@Bean注解
import org.springframework.context.annotation.Configuration; // 引入Spring的@Configuration注解
/**
* ApiBeanConfigSnowflakeID
* @ lanhai
*/
@Configuration // 标注这是一个配置类
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class ApiBeanConfig {
private final ApiConfig apiConfig; // 自动注入ApiConfig配置类的实例
@Bean // 标注这是一个Spring Bean会被Spring容器管理
public Snowflake snowflake() {
// 创建并返回一个Snowflake实例用于生成全局唯一ID
return new Snowflake(apiConfig.getWorkerId(), apiConfig.getDatacenterId());
}
}

@ -0,0 +1,190 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.UserAddrDto;
import com.yami.shop.bean.app.param.AddrParam;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.UserAddrService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import cn.hutool.core.bean.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.Date;
import java.util.List;
/**
* @author lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/p/address") // 定义请求路径的根地址为/p/address
@Tag(name = "地址接口") // 给API文档添加标签描述这个控制器的功能
@AllArgsConstructor // Lombok注解用于生成全参构造函数
public class AddrController {
@Autowired
private UserAddrService userAddrService; // 自动注入用户地址服务类
/**
*
*/
@GetMapping("/list")
@Operation(summary = "用户地址列表" , description = "获取用户的所有地址信息")
public ServerResponseEntity<List<UserAddrDto>> dvyList() {
// 获取当前用户ID
String userId = SecurityUtils.getUser().getUserId();
// 查询用户的所有地址信息,并按是否常用和更新时间倒序排序
List<UserAddr> userAddrs = userAddrService.list(
new LambdaQueryWrapper<UserAddr>()
.eq(UserAddr::getUserId, userId)
.orderByDesc(UserAddr::getCommonAddr)
.orderByDesc(UserAddr::getUpdateTime)
);
// 将地址信息转换成DTO对象并返回
return ServerResponseEntity.success(BeanUtil.copyToList(userAddrs, UserAddrDto.class));
}
@PostMapping("/addAddr")
@Operation(summary = "新增用户地址" , description = "新增用户地址")
public ServerResponseEntity<String> addAddr(@Valid @RequestBody AddrParam addrParam) {
String userId = SecurityUtils.getUser().getUserId();
// 检查地址是否已存在
if (addrParam.getAddrId() != null && addrParam.getAddrId() != 0) {
return ServerResponseEntity.showFailMsg("该地址已存在");
}
// 统计用户已有的地址数量
long addrCount = userAddrService.count(new LambdaQueryWrapper<UserAddr>().eq(UserAddr::getUserId, userId));
UserAddr userAddr = BeanUtil.copyProperties(addrParam, UserAddr.class);
// 如果没有地址,设为常用地址,否则设为非常用
if (addrCount == 0) {
userAddr.setCommonAddr(1);
} else {
userAddr.setCommonAddr(0);
}
userAddr.setUserId(userId);
userAddr.setStatus(1); // 设置状态为有效
userAddr.setCreateTime(new Date()); // 设置创建时间
userAddr.setUpdateTime(new Date()); // 设置更新时间
// 保存地址信息
userAddrService.save(userAddr);
// 如果是常用地址,清除默认地址缓存
if (userAddr.getCommonAddr() == 1) {
userAddrService.removeUserAddrByUserId(0L, userId);
}
return ServerResponseEntity.success("添加地址成功");
}
/**
*
*/
@PutMapping("/updateAddr")
@Operation(summary = "修改订单用户地址" , description = "修改用户地址")
public ServerResponseEntity<String> updateAddr(@Valid @RequestBody AddrParam addrParam) {
String userId = SecurityUtils.getUser().getUserId();
// 根据用户ID和地址ID获取地址信息
UserAddr dbUserAddr = userAddrService.getUserAddrByUserId(addrParam.getAddrId(), userId);
if (dbUserAddr == null) {
return ServerResponseEntity.showFailMsg("该地址已被删除");
}
// 更新地址信息
UserAddr userAddr = BeanUtil.copyProperties(addrParam, UserAddr.class);
userAddr.setUserId(userId);
userAddr.setUpdateTime(new Date());
userAddrService.updateById(userAddr);
// 清除缓存
userAddrService.removeUserAddrByUserId(addrParam.getAddrId(), userId);
userAddrService.removeUserAddrByUserId(0L, userId);
return ServerResponseEntity.success("修改地址成功");
}
/**
*
*/
@DeleteMapping("/deleteAddr/{addrId}")
@Operation(summary = "删除订单用户地址" , description = "根据地址id删除用户地址")
@Parameter(name = "addrId", description = "地址ID" , required = true)
public ServerResponseEntity<String> deleteDvy(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
// 根据用户ID和地址ID获取地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
if (userAddr == null) {
return ServerResponseEntity.showFailMsg("该地址已被删除");
}
// 检查是否为默认地址,默认地址无法删除
if (userAddr.getCommonAddr() == 1) {
return ServerResponseEntity.showFailMsg("默认地址无法删除");
}
// 删除地址信息
userAddrService.removeById(addrId);
userAddrService.removeUserAddrByUserId(addrId, userId);
return ServerResponseEntity.success("删除地址成功");
}
/**
*
*/
@PutMapping("/defaultAddr/{addrId}")
@Operation(summary = "设置默认地址" , description = "根据地址id设置默认地址")
public ServerResponseEntity<String> defaultAddr(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
// 更新默认地址
userAddrService.updateDefaultUserAddr(addrId, userId);
// 清除缓存
userAddrService.removeUserAddrByUserId(0L, userId);
userAddrService.removeUserAddrByUserId(addrId, userId);
return ServerResponseEntity.success("修改地址成功");
}
/**
*
*/
@GetMapping("/addrInfo/{addrId}")
@Operation(summary = "获取地址信息" , description = "根据地址id获取地址信息")
@Parameter(name = "addrId", description = "地址ID" , required = true)
public ServerResponseEntity<UserAddrDto> addrInfo(@PathVariable("addrId") Long addrId) {
String userId = SecurityUtils.getUser().getUserId();
// 根据用户ID和地址ID获取地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(addrId, userId);
if (userAddr == null) {
throw new YamiShopBindException("该地址已被删除");
}
// 转换为DTO对象并返回
return ServerResponseEntity.success(BeanUtil.copyProperties(userAddr, UserAddrDto.class));
}
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import java.util.List; // 引入Java的List接口
import com.yami.shop.service.AreaService; // 引入区域服务类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.GetMapping; // 引入Spring的@GetMapping注解
import org.springframework.web.bind.annotation.RequestMapping; // 引入Spring的@RequestMapping注解
import org.springframework.web.bind.annotation.RestController; // 引入Spring的@RestController注解
import com.yami.shop.bean.model.Area; // 引入区域模型
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import io.swagger.v3.oas.annotations.Parameter; // 引入Swagger的Parameter注解
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
/**
* AreaController
* ID
* @ lgh on 2018/10/26.
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/p/area") // 定义请求路径的根地址为/p/area
@Tag(name = "省市区接口") // 给API文档添加标签描述这个控制器的功能
public class AreaController {
@Autowired
private AreaService areaService; // 自动注入区域服务类
/**
* ID
* @param pid ID(pid0)
* @return
*/
@GetMapping("/listByPid")
@Operation(summary = "获取省市区信息" , description = "根据省市区的pid获取地址信息")
@Parameter(name = "pid", description = "省市区的pid(pid为0获取所有省份)" , required = true)
public ServerResponseEntity<List<Area>> listByPid(Long pid) {
List<Area> list = areaService.listByPid(pid);
return ServerResponseEntity.success(list);
}
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import java.util.List; // 引入Java的List接口
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.*; // 引入Spring Web的注解
import com.yami.shop.bean.app.dto.CategoryDto; // 引入分类DTO类
import com.yami.shop.bean.model.Category; // 引入分类模型类
import com.yami.shop.service.CategoryService; // 引入分类服务类
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import io.swagger.v3.oas.annotations.Parameter; // 引入Swagger的Parameter注解
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
import cn.hutool.core.bean.BeanUtil; // 引入Hutool工具类库中的BeanUtil工具类
/**
* CategoryController
*
* @ lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/category") // 定义请求路径的根地址为/category
@Tag(name = "分类接口") // 给API文档添加标签描述这个控制器的功能
public class CategoryController {
@Autowired
private CategoryService categoryService; // 自动注入分类服务类
/**
*
* @param parentId ID0
* @return
*/
@GetMapping("/categoryInfo")
@Operation(summary = "分类信息列表", description = "获取所有的产品分类信息顶级分类的parentId为0,默认为顶级分类")
@Parameter(name = "parentId", description = "分类ID", required = false)
public ServerResponseEntity<List<CategoryDto>> categoryInfo(@RequestParam(value = "parentId", defaultValue = "0") Long parentId) {
List<Category> categories = categoryService.listByParentId(parentId);
List<CategoryDto> categoryDtos = BeanUtil.copyToList(categories, CategoryDto.class);
return ServerResponseEntity.success(categoryDtos);
}
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import com.yami.shop.service.OrderService; // 引入订单服务类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.GetMapping; // 引入Spring的@GetMapping注解
import org.springframework.web.bind.annotation.RequestMapping; // 引入Spring的@RequestMapping注解
import org.springframework.web.bind.annotation.RestController; // 引入Spring的@RestController注解
import com.yami.shop.bean.app.dto.DeliveryDto; // 引入物流DTO
import com.yami.shop.bean.model.Delivery; // 引入配送模型
import com.yami.shop.bean.model.Order; // 引入订单模型
import com.yami.shop.common.util.Json; // 引入JSON工具类
import com.yami.shop.service.DeliveryService; // 引入配送服务类
import cn.hutool.http.HttpUtil; // 引入Hutool工具类库中的HttpUtil工具类
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import io.swagger.v3.oas.annotations.Parameter; // 引入Swagger的Parameter注解
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
/**
* DeliveryController
*
* @ lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/delivery") // 定义请求路径的根地址为/delivery
@Tag(name = "查看物流接口") // 给API文档添加标签描述这个控制器的功能
public class DeliveryController {
@Autowired
private DeliveryService deliveryService; // 自动注入配送服务类
@Autowired
private OrderService orderService; // 自动注入订单服务类
/**
*
* @param orderNumber
* @return
*/
@GetMapping("/check")
@Operation(summary = "查看物流" , description = "根据订单号查看物流")
@Parameter(name = "orderNumber", description = "订单号" , required = true)
public ServerResponseEntity<DeliveryDto> checkDelivery(String orderNumber) {
Order order = orderService.getOrderByOrderNumber(orderNumber); // 根据订单号获取订单信息
Delivery delivery = deliveryService.getById(order.getDvyId()); // 根据配送ID获取配送信息
String url = delivery.getQueryUrl().replace("{dvyFlowId}", order.getDvyFlowId()); // 构建查询物流信息的URL
String deliveryJson = HttpUtil.get(url); // 发送HTTP GET请求获取物流信息
DeliveryDto deliveryDto = Json.parseObject(deliveryJson, DeliveryDto.class); // 将JSON格式的物流信息转换为DTO对象
deliveryDto.setDvyFlowId(order.getDvyFlowId()); // 设置物流流水号
deliveryDto.setCompanyHomeUrl(delivery.getCompanyHomeUrl()); // 设置物流公司主页URL
deliveryDto.setCompanyName(delivery.getDvyName()); // 设置物流公司名称
return ServerResponseEntity.success(deliveryDto); // 返回物流信息
}
}

@ -0,0 +1,227 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import cn.hutool.core.bean.BeanUtil; // 引入Hutool工具类库中的BeanUtil工具类
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入MyBatis-Plus的分页接口
import com.yami.shop.bean.app.dto.*; // 引入各种DTO类
import com.yami.shop.bean.enums.OrderStatus; // 引入订单状态枚举
import com.yami.shop.bean.model.Order; // 引入订单模型
import com.yami.shop.bean.model.OrderItem; // 引入订单项模型
import com.yami.shop.bean.model.ShopDetail; // 引入店铺详情模型
import com.yami.shop.bean.model.UserAddrOrder; // 引入用户地址订单模型
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import com.yami.shop.common.util.Arith; // 引入算术工具类
import com.yami.shop.common.util.PageParam; // 引入分页参数工具类
import com.yami.shop.security.api.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.*; // 引入各种服务类
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
import io.swagger.v3.oas.annotations.Parameter; // 引入Swagger的Parameter注解
import io.swagger.v3.oas.annotations.Parameters; // 引入Swagger的Parameters注解
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import org.springframework.web.bind.annotation.*;
import java.util.Collections; // 引入Java的Collections工具类
import java.util.List; // 引入Java的List接口
import java.util.Objects; // 引入Java的Objects工具类
/**
* MyOrderController
*
* @ lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/p/myOrder") // 定义请求路径的根地址为/p/myOrder
@Tag(name = "我的订单接口") // 给API文档添加标签描述这个控制器的功能
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class MyOrderController {
private final OrderService orderService; // 注入订单服务类
private final UserAddrOrderService userAddrOrderService; // 注入用户地址订单服务类
private final ProductService productService; // 注入商品服务类
private final SkuService skuService; // 注入SKU服务类
private final MyOrderService myOrderService; // 注入我的订单服务类
private final ShopDetailService shopDetailService; // 注入店铺详情服务类
private final OrderItemService orderItemService; // 注入订单项服务类
/**
*
* @param orderNumber
* @return
*/
@GetMapping("/orderDetail")
@Operation(summary = "订单详情信息", description = "根据订单号获取订单详情信息")
@Parameter(name = "orderNumber", description = "订单号", required = true)
public ServerResponseEntity<OrderShopDto> orderDetail(@RequestParam(value = "orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
OrderShopDto orderShopDto = new OrderShopDto();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (order == null) {
throw new RuntimeException("该订单不存在");
}
if (!Objects.equals(order.getUserId(), userId)) {
throw new RuntimeException("你没有权限获取该订单信息");
}
ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(order.getShopId());
UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
UserAddrDto userAddrDto = BeanUtil.copyProperties(userAddrOrder, UserAddrDto.class);
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
List<OrderItemDto> orderItemList = BeanUtil.copyToList(orderItems, OrderItemDto.class);
orderShopDto.setShopId(shopDetail.getShopId());
orderShopDto.setShopName(shopDetail.getShopName());
orderShopDto.setActualTotal(order.getActualTotal());
orderShopDto.setUserAddrDto(userAddrDto);
orderShopDto.setOrderItemDtos(orderItemList);
orderShopDto.setTransfee(order.getFreightAmount());
orderShopDto.setReduceAmount(order.getReduceAmount());
orderShopDto.setCreateTime(order.getCreateTime());
orderShopDto.setRemarks(order.getRemarks());
orderShopDto.setStatus(order.getStatus());
double total = 0.0;
Integer totalNum = 0;
for (OrderItemDto orderItem : orderShopDto.getOrderItemDtos()) {
total = Arith.add(total, orderItem.getProductTotalAmount());
totalNum += orderItem.getProdCount();
}
orderShopDto.setTotal(total);
orderShopDto.setTotalNum(totalNum);
return ServerResponseEntity.success(orderShopDto);
}
/**
*
* @param status
* @param page
* @return
*/
@GetMapping("/myOrder")
@Operation(summary = "订单列表信息", description = "根据订单状态获取订单列表信息状态为0时获取所有订单")
@Parameters({
@Parameter(name = "status", description = "订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败")
})
public ServerResponseEntity<IPage<MyOrderDto>> myOrder(@RequestParam(value = "status") Integer status, PageParam<MyOrderDto> page) {
String userId = SecurityUtils.getUser().getUserId();
IPage<MyOrderDto> myOrderDtoIpage = myOrderService.pageMyOrderByUserIdAndStatus(page, userId, status);
return ServerResponseEntity.success(myOrderDtoIpage);
}
/**
*
* @param orderNumber
* @return
*/
@PutMapping("/cancel/{orderNumber}")
@Operation(summary = "根据订单号取消订单", description = "根据订单号取消订单")
@Parameter(name = "orderNumber", description = "订单号", required = true)
public ServerResponseEntity<String> cancel(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
throw new YamiShopBindException("订单已支付,无法取消订单");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
// 取消订单
orderService.cancelOrders(Collections.singletonList(order));
// 清除缓存
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
}
return ServerResponseEntity.success();
}
/**
*
* @param orderNumber
* @return
*/
@PutMapping("/receipt/{orderNumber}")
@Operation(summary = "根据订单号确认收货", description = "根据订单号确认收货")
public ServerResponseEntity<String> receipt(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
if (!Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value())) {
throw new YamiShopBindException("订单未发货,无法确认收货");
}
List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
order.setOrderItems(orderItems);
// 确认收货
orderService.confirmOrder(Collections.singletonList(order));
for (OrderItem orderItem : orderItems) {
productService.removeProductCacheByProdId(orderItem.getProdId());
skuService.removeSkuCacheBySkuId(orderItem.getSkuId(), orderItem.getProdId());
}
return ServerResponseEntity.success();
}
/**
*
* @param orderNumber
* @return
*/
@DeleteMapping("/{orderNumber}")
@Operation(summary = "根据订单号删除订单", description = "根据订单号删除订单")
@Parameter(name = "orderNumber", description = "订单号", required = true)
public ServerResponseEntity<String> delete(@PathVariable("orderNumber") String orderNumber) {
String userId = SecurityUtils.getUser().getUserId();
Order order = orderService.getOrderByOrderNumber(orderNumber);
if (order == null) {
throw new YamiShopBindException("该订单不存在");
}
if (!Objects.equals(order.getUserId(), userId)) {
throw new YamiShopBindException("你没有权限获取该订单信息");
}
if (!Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value()) && !Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
throw new YamiShopBindException("订单未完成或未关闭,无法删除订单");
}
// 删除订单
orderService.deleteOrders(Collections.singletonList(order));
return ServerResponseEntity.success("删除成功");
}
/**
*
*/
@GetMapping("/orderCount")
@Operation(summary = "获取我的订单订单数量", description = "获取我的订单订单数量")
public ServerResponseEntity<OrderCountData> getOrderCount() {
String userId = SecurityUtils.getUser().getUserId();
OrderCountData orderCountMap = orderService.getOrderCount(userId);
return ServerResponseEntity.success(orderCountMap);
}
}

@ -0,0 +1,183 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import cn.hutool.core.collection.CollectionUtil; // 引入Hutool工具类库中的CollectionUtil工具类
import com.yami.shop.bean.app.dto.*; // 引入各种DTO类
import com.yami.shop.bean.app.param.OrderParam; // 引入订单参数类
import com.yami.shop.bean.app.param.OrderShopParam; // 引入订单店铺参数类
import com.yami.shop.bean.app.param.SubmitOrderParam; // 引入提交订单参数类
import com.yami.shop.bean.event.ConfirmOrderEvent; // 引入确认订单事件类
import com.yami.shop.bean.model.Order; // 引入订单模型类
import com.yami.shop.bean.model.UserAddr; // 引入用户地址模型类
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.util.Arith; // 引入算术工具类
import com.yami.shop.security.api.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.*; // 引入各种服务类
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
import cn.hutool.core.bean.BeanUtil; // 引入Hutool工具类库中的BeanUtil工具类
import org.springframework.beans.factory.annotation.Autowired; // 引入Spring的@Autowired注解
import org.springframework.context.ApplicationContext; // 引入Spring的ApplicationContext类
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.*; // 引入Spring Web的注解
import jakarta.validation.Valid; // 引入Jakarta Validation的Valid注解
import java.util.ArrayList; // 引入Java的ArrayList类
import java.util.List; // 引入Java的List接口
import java.util.Objects; // 引入Java的Objects工具类
/**
* OrderController
* @ lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/p/order") // 定义请求路径的根地址为/p/order
@Tag(name = "订单接口") // 给API文档添加标签描述这个控制器的功能
public class OrderController {
@Autowired
private OrderService orderService; // 自动注入订单服务类
@Autowired
private SkuService skuService; // 自动注入SKU服务类
@Autowired
private ProductService productService; // 自动注入商品服务类
@Autowired
private UserAddrService userAddrService; // 自动注入用户地址服务类
@Autowired
private BasketService basketService; // 自动注入购物车服务类
@Autowired
private ApplicationContext applicationContext; // 自动注入Spring应用上下文
/**
*
* @param orderParam
* @return
*/
@PostMapping("/confirm")
@Operation(summary = "结算,生成订单信息" , description = "传入下单所需要的参数进行下单")
public ServerResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) {
String userId = SecurityUtils.getUser().getUserId();
// 获取订单的地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(orderParam.getAddrId(), userId);
UserAddrDto userAddrDto = BeanUtil.copyProperties(userAddr, UserAddrDto.class);
// 获取用户提交的购物车商品项
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItemsByOrderItems(orderParam.getBasketIds(), orderParam.getOrderItem(), userId);
if (CollectionUtil.isEmpty(shopCartItems)) {
throw new YamiShopBindException("请选择您需要的商品加入购物车");
}
// 根据店铺组装购物车中的商品信息
List<ShopCartDto> shopCarts = basketService.getShopCarts(shopCartItems);
// 生成完整的订单信息
ShopCartOrderMergerDto shopCartOrderMergerDto = new ShopCartOrderMergerDto();
shopCartOrderMergerDto.setUserAddr(userAddrDto);
List<ShopCartOrderDto> shopCartOrders = new ArrayList<>();
double actualTotal = 0.0;
double total = 0.0;
int totalCount = 0;
double orderReduce = 0.0;
for (ShopCartDto shopCart : shopCarts) {
ShopCartOrderDto shopCartOrder = new ShopCartOrderDto();
shopCartOrder.setShopId(shopCart.getShopId());
shopCartOrder.setShopName(shopCart.getShopName());
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
List<ShopCartItemDto> shopAllShopCartItems = new ArrayList<>();
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
List<ShopCartItemDto> discountShopCartItems = shopCartItemDiscount.getShopCartItems();
shopAllShopCartItems.addAll(discountShopCartItems);
}
shopCartOrder.setShopCartItemDiscounts(shopCartItemDiscounts);
applicationContext.publishEvent(new ConfirmOrderEvent(shopCartOrder, orderParam, shopAllShopCartItems));
actualTotal = Arith.add(actualTotal, shopCartOrder.getActualTotal());
total = Arith.add(total, shopCartOrder.getTotal());
totalCount += shopCartOrder.getTotalCount();
orderReduce = Arith.add(orderReduce, shopCartOrder.getShopReduce());
shopCartOrders.add(shopCartOrder);
}
shopCartOrderMergerDto.setActualTotal(actualTotal);
shopCartOrderMergerDto.setTotal(total);
shopCartOrderMergerDto.setTotalCount(totalCount);
shopCartOrderMergerDto.setShopCartOrders(shopCartOrders);
shopCartOrderMergerDto.setOrderReduce(orderReduce);
shopCartOrderMergerDto = orderService.putConfirmOrderCache(userId, shopCartOrderMergerDto);
return ServerResponseEntity.success(shopCartOrderMergerDto);
}
/**
*
* @param submitOrderParam
* @return
*/
@PostMapping("/submit")
@Operation(summary = "提交订单,返回支付流水号" , description = "根据传入的参数判断是否为购物车提交订单,同时对购物车进行删除,用户开始进行支付")
public ServerResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) {
String userId = SecurityUtils.getUser().getUserId();
ShopCartOrderMergerDto mergerOrder = orderService.getConfirmOrderCache(userId);
if (mergerOrder == null) {
throw new YamiShopBindException("订单已过期,请重新下单");
}
List<OrderShopParam> orderShopParams = submitOrderParam.getOrderShopParam();
List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
// 设置备注
if (CollectionUtil.isNotEmpty(orderShopParams)) {
for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
for (OrderShopParam orderShopParam : orderShopParams) {
if (Objects.equals(shopCartOrder.getShopId(), orderShopParam.getShopId())) {
shopCartOrder.setRemarks(orderShopParam.getRemarks());
}
}
}
}
List<Order> orders = orderService.submit(userId, mergerOrder);
StringBuilder orderNumbers = new StringBuilder();
for (Order order : orders) {
orderNumbers.append(order.getOrderNumber()).append(",");
}
orderNumbers.deleteCharAt(orderNumbers.length() - 1);
boolean isShopCartOrder = false;
// 移除缓存
for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
Long basketId = shopCartItem.getBasketId();
if (basketId != null && basketId != 0) {
isShopCartOrder = true;
}
skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(), shopCartItem.getProdId());
productService.removeProductCacheByProdId(shopCartItem.getProdId());
}
}
}
// 购物车提交订单时(即有购物车ID时)
if (isShopCartOrder) {
basketService.removeShopCartItemsCacheByUserId(userId);
}
orderService.removeConfirmOrderCache(userId);
return ServerResponseEntity.success(new OrderNumbersDto(orderNumbers.toString()));
}
}

@ -0,0 +1,69 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import com.yami.shop.bean.app.param.PayParam; // 引入支付参数类
import com.yami.shop.bean.pay.PayInfoDto; // 引入支付信息DTO类
import com.yami.shop.security.api.model.YamiUser; // 引入用户模型类
import com.yami.shop.security.api.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.PayService; // 引入支付服务类
import io.swagger.v3.oas.annotations.tags.Tag; // 引入Swagger的Tag注解
import io.swagger.v3.oas.annotations.Operation; // 引入Swagger的Operation注解
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import com.yami.shop.common.response.ServerResponseEntity; // 引入服务器响应实体类
import org.springframework.web.bind.annotation.*; // 引入Spring Web的注解
/**
* PayController
* @ lanhai
*/
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/p/order") // 定义请求路径的根地址为/p/order
@Tag(name = "订单接口") // 给API文档添加标签描述这个控制器的功能
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class PayController {
private final PayService payService; // 自动注入支付服务类
/**
*
* @param payParam
* @return
*/
@PostMapping("/pay")
@Operation(summary = "根据订单号进行支付", description = "根据订单号进行支付")
public ServerResponseEntity<Void> pay(@RequestBody PayParam payParam) {
YamiUser user = SecurityUtils.getUser();
String userId = user.getUserId();
PayInfoDto payInfo = payService.pay(userId, payParam); // 调用支付服务进行支付
payService.paySuccess(payInfo.getPayNo(), ""); // 调用支付成功处理
return ServerResponseEntity.success(); // 返回成功响应
}
/**
*
* @param payParam
* @return
*/
@PostMapping("/normalPay")
@Operation(summary = "根据订单号进行支付", description = "根据订单号进行支付")
public ServerResponseEntity<Boolean> normalPay(@RequestBody PayParam payParam) {
YamiUser user = SecurityUtils.getUser();
String userId = user.getUserId();
PayInfoDto pay = payService.pay(userId, payParam); // 调用支付服务进行支付
// 根据内部订单号更新订单结算信息
payService.paySuccess(pay.getPayNo(), "");
return ServerResponseEntity.success(true); // 返回成功响应
}
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.controller; // 定义类所在的包
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import org.springframework.web.bind.annotation.RequestMapping; // 引入Spring的@RequestMapping注解
import org.springframework.web.bind.annotation.RestController; // 引入Spring的@RestController注解
import io.swagger.v3.oas.annotations.Hidden; // 引入Swagger的Hidden注解
/**
* PayNoticeController
* @ lanhai
*/
@Hidden // 隐藏这个控制器不在Swagger文档中展示
@RestController // 标注这是一个控制器类并且其返回结果直接写入HTTP响应体中而不是视图名称
@RequestMapping("/notice/pay") // 定义请求路径的根地址为/notice/pay
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class PayNoticeController {
// 模拟支付不需要回调
// /**
// * 小程序支付
// */
// private final WxPayService wxMiniPayService;
//
// private final PayService payService;
//
// @RequestMapping("/order")
// public ServerResponseEntity<Void> submit(@RequestBody String xmlData) throws WxPayException {
// WxPayOrderNotifyResult parseOrderNotifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
//
// String payNo = parseOrderNotifyResult.getOutTradeNo();
// String bizPayNo = parseOrderNotifyResult.getTransactionId();
//
// // 根据内部订单号更新order settlement
// payService.paySuccess(payNo, bizPayNo);
//
// return ServerResponseEntity.success();
// }
}

@ -0,0 +1,100 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.listener; // 定义类所在的包
import com.yami.shop.bean.app.dto.ShopCartItemDto; // 引入购物车项目DTO
import com.yami.shop.bean.app.dto.ShopCartOrderDto; // 引入购物车订单DTO
import com.yami.shop.bean.app.param.OrderParam; // 引入订单参数
import com.yami.shop.bean.event.ConfirmOrderEvent; // 引入确认订单事件
import com.yami.shop.bean.model.Product; // 引入商品模型
import com.yami.shop.bean.model.Sku; // 引入SKU模型
import com.yami.shop.bean.model.UserAddr; // 引入用户地址模型
import com.yami.shop.bean.order.ConfirmOrderOrder; // 引入确认订单顺序
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.util.Arith; // 引入算术工具类
import com.yami.shop.security.api.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.ProductService; // 引入商品服务类
import com.yami.shop.service.SkuService; // 引入SKU服务类
import com.yami.shop.service.TransportManagerService; // 引入运输管理服务类
import com.yami.shop.service.UserAddrService; // 引入用户地址服务类
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import org.springframework.context.event.EventListener; // 引入Spring的事件监听注解
import org.springframework.core.annotation.Order; // 引入Spring的Order注解
import org.springframework.stereotype.Component; // 引入Spring的Component注解
/**
*
* ConfirmOrderListener
* @ LGH
*/
@Component("defaultConfirmOrderListener") // 标注这是一个Spring组件并且以defaultConfirmOrderListener为组件名称
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class ConfirmOrderListener {
private final UserAddrService userAddrService; // 自动注入用户地址服务类
private final TransportManagerService transportManagerService; // 自动注入运输管理服务类
private final ProductService productService; // 自动注入商品服务类
private final SkuService skuService; // 自动注入SKU服务类
/**
*
* @param event
*/
@EventListener(ConfirmOrderEvent.class) // 标注这是一个事件监听器监听ConfirmOrderEvent事件
@Order(ConfirmOrderOrder.DEFAULT) // 设置事件监听的顺序
public void defaultConfirmOrderEvent(ConfirmOrderEvent event) {
ShopCartOrderDto shopCartOrderDto = event.getShopCartOrderDto(); // 获取购物车订单DTO
OrderParam orderParam = event.getOrderParam(); // 获取订单参数
String userId = SecurityUtils.getUser().getUserId(); // 获取当前用户ID
// 订单的地址信息
UserAddr userAddr = userAddrService.getUserAddrByUserId(orderParam.getAddrId(), userId);
double total = 0.0; // 总金额
int totalCount = 0; // 总商品数量
double transfee = 0.0; // 总运费
for (ShopCartItemDto shopCartItem : event.getShopCartItems()) {
// 获取商品信息
Product product = productService.getProductByProdId(shopCartItem.getProdId());
// 获取sku信息
Sku sku = skuService.getSkuBySkuId(shopCartItem.getSkuId());
if (product == null || sku == null) {
throw new YamiShopBindException("购物车包含无法识别的商品"); // 商品或SKU为空抛出异常
}
if (product.getStatus() != 1 || sku.getStatus() != 1) {
throw new YamiShopBindException("商品[" + sku.getProdName() + "]已下架"); // 商品或SKU已下架抛出异常
}
totalCount = shopCartItem.getProdCount() + totalCount; // 累加商品数量
total = Arith.add(shopCartItem.getProductTotalAmount(), total); // 累加商品总金额
// 用户地址如果为空,则表示该用户从未设置过任何地址相关信息
if (userAddr != null) {
// 每个产品的运费相加
transfee = Arith.add(transfee, transportManagerService.calculateTransfee(shopCartItem, userAddr));
}
shopCartItem.setActualTotal(shopCartItem.getProductTotalAmount()); // 设置实际总金额
shopCartOrderDto.setActualTotal(Arith.add(total, transfee)); // 设置订单实际总金额
shopCartOrderDto.setTotal(total); // 设置订单总金额
shopCartOrderDto.setTotalCount(totalCount); // 设置订单总商品数量
shopCartOrderDto.setTransfee(transfee); // 设置订单总运费
}
}
}

@ -0,0 +1,270 @@
/*
* Copyright (c) 2018-2999 广 All rights reserved.
*
* https://www.mall4j.com/
*
*
*
*
*/
package com.yami.shop.api.listener; // 定义类所在的包
import cn.hutool.core.lang.Snowflake; // 引入Hutool工具类库中的Snowflake工具类
import cn.hutool.core.util.StrUtil; // 引入Hutool工具类库中的StrUtil工具类
import com.yami.shop.bean.app.dto.*; // 引入各种DTO类
import com.yami.shop.bean.enums.OrderStatus; // 引入订单状态枚举类
import com.yami.shop.bean.event.SubmitOrderEvent; // 引入提交订单事件类
import com.yami.shop.bean.model.*; // 引入各种模型类
import com.yami.shop.bean.order.SubmitOrderOrder; // 引入提交订单顺序类
import com.yami.shop.common.constants.Constant; // 引入常量类
import com.yami.shop.common.exception.YamiShopBindException; // 引入自定义异常类
import com.yami.shop.common.util.Arith; // 引入算术工具类
import com.yami.shop.dao.*; // 引入各种数据访问对象
import com.yami.shop.security.api.util.SecurityUtils; // 引入安全工具类
import com.yami.shop.service.*; // 引入各种服务类
import lombok.AllArgsConstructor; // 引入Lombok的@AllArgsConstructor注解
import cn.hutool.core.bean.BeanUtil; // 引入Hutool工具类库中的BeanUtil工具类
import org.springframework.context.event.EventListener; // 引入Spring的EventListener注解
import org.springframework.core.annotation.Order; // 引入Spring的Order注解
import org.springframework.stereotype.Component; // 引入Spring的Component注解
import java.util.*; // 引入Java的各种集合类
/**
*
*
* @ LGH
*/
@Component("defaultSubmitOrderListener") // 标注这是一个Spring组件并且以defaultSubmitOrderListener为组件名称
@AllArgsConstructor // 使用Lombok注解生成全参构造函数
public class SubmitOrderListener {
private final UserAddrOrderService userAddrOrderService; // 自动注入用户地址订单服务类
private final ProductService productService; // 自动注入商品服务类
private final SkuService skuService; // 自动注入SKU服务类
private final Snowflake snowflake; // 自动注入雪花算法实例
private final OrderItemMapper orderItemMapper; // 自动注入订单项数据访问对象
private final SkuMapper skuMapper; // 自动注入SKU数据访问对象
private final ProductMapper productMapper; // 自动注入商品数据访问对象
private final OrderMapper orderMapper; // 自动注入订单数据访问对象
private final OrderSettlementMapper orderSettlementMapper; // 自动注入订单结算数据访问对象
private final BasketMapper basketMapper; // 自动注入购物车数据访问对象
/**
*
* @param event
*/
@EventListener(SubmitOrderEvent.class)
@Order(SubmitOrderOrder.DEFAULT)
public void defaultSubmitOrderListener(SubmitOrderEvent event) {
Date now = new Date();
String userId = SecurityUtils.getUser().getUserId();
ShopCartOrderMergerDto mergerOrder = event.getMergerOrder();
// 订单商品参数
List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
List<Long> basketIds = new ArrayList<>();
// 商品skuId为key需要更新的sku为value的map
Map<Long, Sku> skuStocksMap = new HashMap<>(16);
// 商品productId为key需要更新的product为value的map
Map<Long, Product> prodStocksMap = new HashMap<>(16);
// 把订单地址保存到数据库
UserAddrOrder userAddrOrder = BeanUtil.copyProperties(mergerOrder.getUserAddr(), UserAddrOrder.class);
if (userAddrOrder == null) {
throw new YamiShopBindException("请填写收货地址");
}
userAddrOrder.setUserId(userId);
userAddrOrder.setCreateTime(now);
userAddrOrderService.save(userAddrOrder);
// 订单地址id
Long addrOrderId = userAddrOrder.getAddrOrderId();
// 每个店铺生成一个订单
for (ShopCartOrderDto shopCartOrderDto : shopCartOrders) {
createOrder(event, now, userId, basketIds, skuStocksMap, prodStocksMap, addrOrderId, shopCartOrderDto);
}
// 删除购物车的商品信息
if (!basketIds.isEmpty()) {
basketMapper.deleteShopCartItemsByBasketIds(userId, basketIds);
}
// 更新sku库存
skuStocksMap.forEach((key, sku) -> {
if (skuMapper.updateStocks(sku) == 0) {
skuService.removeSkuCacheBySkuId(key, sku.getProdId());
throw new YamiShopBindException("商品:[" + sku.getProdName() + "]库存不足");
}
});
// 更新商品库存
prodStocksMap.forEach((prodId, prod) -> {
if (productMapper.updateStocks(prod) == 0) {
productService.removeProductCacheByProdId(prodId);
throw new YamiShopBindException("商品:[" + prod.getProdName() + "]库存不足");
}
});
}
private void createOrder(SubmitOrderEvent event, Date now, String userId, List<Long> basketIds, Map<Long, Sku> skuStocksMap, Map<Long, Product> prodStocksMap, Long addrOrderId, ShopCartOrderDto shopCartOrderDto) {
// 使用雪花算法生成的订单号
String orderNumber = String.valueOf(snowflake.nextId());
shopCartOrderDto.setOrderNumber(orderNumber);
Long shopId = shopCartOrderDto.getShopId();
// 订单商品名称
StringBuilder orderProdName = new StringBuilder(100);
List<OrderItem> orderItems = new ArrayList<>();
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
for (ShopCartItemDto shopCartItem : shopCartItems) {
Sku sku = checkAndGetSku(shopCartItem.getSkuId(), shopCartItem, skuStocksMap);
Product product = checkAndGetProd(shopCartItem.getProdId(), shopCartItem, prodStocksMap);
OrderItem orderItem = getOrderItem(now, userId, orderNumber, shopId, orderProdName, shopCartItem, sku, product);
orderItems.add(orderItem);
if (shopCartItem.getBasketId() != null && shopCartItem.getBasketId() != 0) {
basketIds.add(shopCartItem.getBasketId());
}
}
}
orderProdName.subSequence(0, Math.min(orderProdName.length() - 1, 100));
if (orderProdName.lastIndexOf(Constant.COMMA) == orderProdName.length() - 1) {
orderProdName.deleteCharAt(orderProdName.length() - 1);
}
// 订单信息
com.yami.shop.bean.model.Order order = getOrder(now, userId, addrOrderId, shopCartOrderDto, orderNumber, shopId, orderProdName, orderItems);
event.getOrders().add(order);
// 插入订单结算表
OrderSettlement orderSettlement = new OrderSettlement();
orderSettlement.setUserId(userId);
orderSettlement.setIsClearing(0);
orderSettlement.setCreateTime(now);
orderSettlement.setOrderNumber(orderNumber);
orderSettlement.setPayAmount(order.getActualTotal());
orderSettlement.setPayStatus(0);
orderSettlement.setVersion(0);
orderSettlementMapper.insert(orderSettlement);
}
private com.yami.shop.bean.model.Order getOrder(Date now, String userId, Long addrOrderId, ShopCartOrderDto shopCartOrderDto, String orderNumber, Long shopId, StringBuilder orderProdName, List<OrderItem> orderItems) {
com.yami.shop.bean.model.Order order = new com.yami.shop.bean.model.Order();
order.setShopId(shopId);
order.setOrderNumber(orderNumber);
order.setProdName(orderProdName.toString()); // 订单商品名称
order.setUserId(userId); // 用户ID
order.setTotal(shopCartOrderDto.getTotal()); // 商品总额
order.setActualTotal(shopCartOrderDto.getActualTotal()); // 实际总额
order.setStatus(OrderStatus.UNPAY.value()); // 订单状态为未支付
order.setUpdateTime(now);
order.setCreateTime(now);
order.setIsPayed(0);
order.setDeleteStatus(0);
order.setProductNums(shopCartOrderDto.getTotalCount());
order.setAddrOrderId(addrOrderId);
order.setReduceAmount(Arith.sub(Arith.add(shopCartOrderDto.getTotal(), shopCartOrderDto.getTransfee()), shopCartOrderDto.getActualTotal()));
order.setFreightAmount(shopCartOrderDto.getTransfee());
order.setRemarks(shopCartOrderDto.getRemarks());
order.setOrderItems(orderItems);
return order;
}
private OrderItem getOrderItem(Date now, String userId, String orderNumber, Long shopId, StringBuilder orderProdName, ShopCartItemDto shopCartItem, Sku sku, Product product) {
OrderItem orderItem = new OrderItem();
orderItem.setShopId(shopId);
orderItem.setOrderNumber(orderNumber);
orderItem.setProdId(sku.getProdId());
orderItem.setSkuId(sku.getSkuId());
orderItem.setSkuName(sku.getSkuName());
orderItem.setProdCount(shopCartItem.getProdCount());
orderItem.setProdName(sku.getProdName());
orderItem.setPic(StrUtil.isBlank(sku.getPic()) ? product.getPic() : sku.getPic());
orderItem.setPrice(shopCartItem.getPrice());
orderItem.setUserId(userId);
orderItem.setProductTotalAmount(shopCartItem.getProductTotalAmount());
orderItem.setRecTime(now);
orderItem.setCommSts(0);
orderItem.setBasketDate(shopCartItem.getBasketDate());
orderProdName.append(orderItem.getProdName()).append(",");
//推广员卡号
orderItem.setDistributionCardNo(shopCartItem.getDistributionCardNo());
return orderItem;
}
@SuppressWarnings({"Duplicates"})
private Product checkAndGetProd(Long prodId, ShopCartItemDto shopCartItem, Map<Long, Product> prodStocksMap) {
Product product = productService.getProductByProdId(prodId);
if (product == null) {
throw new YamiShopBindException("购物车包含无法识别的商品");
}
if (product.getStatus() != 1) {
throw new YamiShopBindException("商品[" + product.getProdName() + "]已下架");
}
// 商品需要改变的库存
Product mapProduct = prodStocksMap.get(prodId);
if (mapProduct == null) {
mapProduct = new Product();
mapProduct.setTotalStocks(0);
mapProduct.setProdId(prodId);
mapProduct.setProdName(product.getProdName());
}
if (product.getTotalStocks() != -1) {
mapProduct.setTotalStocks(mapProduct.getTotalStocks() + shopCartItem.getProdCount());
prodStocksMap.put(product.getProdId(), mapProduct);
}
// -1为无限库存
if (product.getTotalStocks() != -1 && mapProduct.getTotalStocks() > product.getTotalStocks()) {
throw new YamiShopBindException("商品:[" + product.getProdName() + "]库存不足");
}
return product;
}
@SuppressWarnings({"Duplicates"})
private Sku checkAndGetSku(Long skuId, ShopCartItemDto shopCartItem, Map<Long, Sku> skuStocksMap) {
// 获取sku信息
Sku sku = skuService.getSkuBySkuId(skuId);
if (sku == null) {
throw new YamiShopBindException("购物车包含无法识别的商品");
}
if (sku.getStatus() != 1) {
throw new YamiShopBindException("商品[" + sku.getProdName() + "]已下架");
}
// -1为无限库存
if (sku.getStocks() != -1 && shopCartItem.getProdCount() > sku.getStocks()) {
throw new YamiShopBindException("商品:[" + sku.getProdName() + "]库存不足");
}
if (sku.getStocks() != -1) {
Sku mapSku = new Sku();
mapSku.setProdId(sku.getProdId());
// 这里的库存是改变的库存
mapSku.setStocks(shopCartItem.getProdCount());
mapSku.setSkuId(sku.getSkuId());
mapSku.setProdName(sku.getProdName());
skuStocksMap.put(sku.getSkuId(), mapSku);
}
return sku;
}
}
Loading…
Cancel
Save