forked from gushen/sunway-user-system
完成了用户地址的增加修改删除功能,完成了订单模块:创建订单、订单分页查询、订单状态更新...
This commit is contained in:
@@ -24,4 +24,7 @@ public class MessageConstant {
|
||||
public static final String CART_ITEM_NOT_FOUND = "购物车记录不存在";
|
||||
public static final String STOCK_INSUFFICIENT = "库存不足,无法添加";
|
||||
public static final String NO_PERMISSION = "没有权限";
|
||||
public static final String CART_ITEM_EMPTY = "购物车为空";
|
||||
public static final String ADDRESS_ID_NULL = "地址ID不能为空";
|
||||
public static final String ADDRESS_NOT_FOUND = "地址不存在";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// OrderController.java
|
||||
package icu.sunway.ai_spring_example.Controllers;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import icu.sunway.ai_spring_example.Common.Response.ResponseEntity;
|
||||
import icu.sunway.ai_spring_example.Service.OrderService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/order")
|
||||
@Slf4j
|
||||
public class OrderController {
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity createOrder(@Validated @RequestBody OrderDTO orderDTO) {
|
||||
log.info("创建订单: {}", orderDTO);
|
||||
Long orderId = orderService.createOrder(orderDTO);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orderId", orderId);
|
||||
return ResponseEntity.success("订单创建成功", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询订单列表
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public ResponseEntity<Map<String, Object>> getOrderPage(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size,
|
||||
@RequestParam Long userId,
|
||||
@RequestParam(required = false) Integer status
|
||||
) {
|
||||
log.info("查询订单列表: page={}, size={}, userId={}, status={}",
|
||||
page, size, userId, status);
|
||||
|
||||
Page<OrderListVO> orderPage = orderService.getOrderPage(page, size, userId, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", orderPage.getRecords());
|
||||
result.put("total", orderPage.getTotal());
|
||||
result.put("page", page);
|
||||
result.put("size", size);
|
||||
|
||||
return ResponseEntity.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单详情
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<OrderVO> getOrderDetail(
|
||||
@PathVariable Long id,
|
||||
@RequestParam Long userId
|
||||
) {
|
||||
log.info("查询订单详情: id={}, userId={}", id, userId);
|
||||
OrderVO orderVO = orderService.getOrderDetail(id, userId);
|
||||
return ResponseEntity.success(orderVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
*/
|
||||
@PutMapping("/status")
|
||||
public ResponseEntity updateOrderStatus(@Validated @RequestBody OrderStatusDTO statusDTO) {
|
||||
log.info("更新订单状态: {}", statusDTO);
|
||||
orderService.updateOrderStatus(statusDTO);
|
||||
return ResponseEntity.success("订单状态更新成功");
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,22 @@ import icu.sunway.ai_spring_example.Common.Constant.StatusConstant;
|
||||
import icu.sunway.ai_spring_example.Common.Properties.JwtProperties;
|
||||
import icu.sunway.ai_spring_example.Common.Response.ResponseEntity;
|
||||
import icu.sunway.ai_spring_example.Common.Utils.JwtUtil;
|
||||
import icu.sunway.ai_spring_example.Service.UserAddressService;
|
||||
import icu.sunway.ai_spring_example.Service.UserService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.UserDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.User;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.UserLoginVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@@ -29,6 +34,9 @@ public class UserController {
|
||||
|
||||
@Autowired
|
||||
private JwtProperties jwtProperties;
|
||||
|
||||
@Autowired
|
||||
private UserAddressService userAddressService;
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<UserLoginVO> login(@RequestBody UserDTO userDTO){
|
||||
log.info("用户登录:{}",userDTO);
|
||||
@@ -76,4 +84,64 @@ public class UserController {
|
||||
userService.update(userDTO);
|
||||
return ResponseEntity.success("更新成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加地址
|
||||
*/
|
||||
@PostMapping("/address")
|
||||
public ResponseEntity addAddress(@Validated @RequestBody UserAddressDTO addressDTO) {
|
||||
log.info("添加用户地址: {}", addressDTO);
|
||||
userAddressService.addAddress(addressDTO);
|
||||
return ResponseEntity.success("地址添加成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新地址
|
||||
*/
|
||||
@PutMapping("/address")
|
||||
public ResponseEntity updateAddress(@Validated @RequestBody UserAddressDTO addressDTO) {
|
||||
log.info("更新用户地址: {}", addressDTO);
|
||||
userAddressService.updateAddress(addressDTO);
|
||||
return ResponseEntity.success("地址更新成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除地址
|
||||
*/
|
||||
@DeleteMapping("/address/{id}")
|
||||
public ResponseEntity deleteAddress(@PathVariable Long id, @RequestParam Long userId) {
|
||||
log.info("删除用户地址: id={}, userId={}", id, userId);
|
||||
userAddressService.deleteAddress(id, userId);
|
||||
return ResponseEntity.success("地址删除成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户地址列表
|
||||
*/
|
||||
@GetMapping("/address")
|
||||
public ResponseEntity<List<UserAddress>> getAddressList(@RequestParam Long userId) {
|
||||
log.info("查询用户地址列表: userId={}", userId);
|
||||
List<UserAddress> addressList = userAddressService.getAddressListByUserId(userId);
|
||||
return ResponseEntity.success(addressList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询地址详情
|
||||
*/
|
||||
@GetMapping("/address/{id}")
|
||||
public ResponseEntity<UserAddress> getAddressDetail(@PathVariable Long id, @RequestParam Long userId) {
|
||||
log.info("查询地址详情: id={}, userId={}", id, userId);
|
||||
UserAddress address = userAddressService.getAddressById(id, userId);
|
||||
return ResponseEntity.success(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认地址
|
||||
*/
|
||||
@PutMapping("/address/{id}/default")
|
||||
public ResponseEntity setDefaultAddress(@PathVariable Long id, @RequestParam Long userId) {
|
||||
log.info("设置默认地址: id={}, userId={}", id, userId);
|
||||
userAddressService.setDefaultAddress(id, userId);
|
||||
return ResponseEntity.success("默认地址设置成功");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// OrderInfoMapper.java
|
||||
package icu.sunway.ai_spring_example.Mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.OrderInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// OrderItemMapper.java
|
||||
package icu.sunway.ai_spring_example.Mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.OrderItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface OrderItemMapper extends BaseMapper<OrderItem> {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// UserAddressMapper.java
|
||||
package icu.sunway.ai_spring_example.Mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface UserAddressMapper extends BaseMapper<UserAddress> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
// OrderServiceImpl.java
|
||||
package icu.sunway.ai_spring_example.Service.Impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import icu.sunway.ai_spring_example.Common.Exception.BusinessException;
|
||||
import icu.sunway.ai_spring_example.Common.Constant.MessageConstant;
|
||||
import icu.sunway.ai_spring_example.Mapper.*;
|
||||
import icu.sunway.ai_spring_example.Service.OrderService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.*;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {
|
||||
|
||||
@Autowired
|
||||
private OrderInfoMapper orderInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private OrderItemMapper orderItemMapper;
|
||||
|
||||
@Autowired
|
||||
private ShoppingCartMapper shoppingCartMapper;
|
||||
|
||||
@Autowired
|
||||
private ProductSkuMapper productSkuMapper;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ProductMapper productMapper;
|
||||
/**
|
||||
* 生成唯一订单编号
|
||||
*/
|
||||
private String generateOrderNo() {
|
||||
// 格式: 年月日时分秒 + 3位随机数
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
||||
String dateStr = LocalDateTime.now().format(formatter);
|
||||
Random random = new Random();
|
||||
int randomNum = random.nextInt(900) + 100; // 100-999的随机数
|
||||
return "ORDER" + dateStr + randomNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long createOrder(OrderDTO orderDTO) {
|
||||
// 1. 查询用户购物车中已勾选的商品
|
||||
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ShoppingCart::getUserId, orderDTO.getUserId())
|
||||
.eq(ShoppingCart::getChecked, 1) // 只查询已勾选的商品
|
||||
.eq(ShoppingCart::getIsDeleted, 0);
|
||||
|
||||
List<ShoppingCart> cartList = shoppingCartMapper.selectList(queryWrapper);
|
||||
if (cartList == null || cartList.isEmpty()) {
|
||||
throw new BusinessException(MessageConstant.CART_ITEM_EMPTY);
|
||||
}
|
||||
|
||||
// 2. 验证库存并计算总金额
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
//TODO 改运费
|
||||
BigDecimal freightAmount = new BigDecimal("0.00"); // 假设运费0元
|
||||
|
||||
for (ShoppingCart cart : cartList) {
|
||||
ProductSku sku = productSkuMapper.selectById(cart.getSkuId());
|
||||
if (sku == null) {
|
||||
throw new BusinessException("商品规格不存在: " + cart.getSkuId());
|
||||
}
|
||||
|
||||
if (sku.getStock() < cart.getCount()) {
|
||||
throw new BusinessException("商品 " + sku.getSkuName() + " 库存不足");
|
||||
}
|
||||
|
||||
// 计算商品总价
|
||||
BigDecimal itemTotal = sku.getPrice().multiply(new BigDecimal(cart.getCount()));
|
||||
totalAmount = totalAmount.add(itemTotal);
|
||||
}
|
||||
|
||||
// 3. 创建订单主表记录
|
||||
OrderInfo orderInfo = new OrderInfo();
|
||||
BeanUtils.copyProperties(orderDTO, orderInfo);
|
||||
String orderNo = generateOrderNo();
|
||||
orderInfo.setOrderNo(orderNo);
|
||||
orderInfo.setTotalAmount(totalAmount);
|
||||
orderInfo.setFreightAmount(freightAmount);
|
||||
orderInfo.setPayAmount(totalAmount.add(freightAmount)); // 实付金额 = 商品总价 + 运费
|
||||
orderInfo.setStatus(0); // 初始状态:待付款
|
||||
orderInfo.setCreateTime(LocalDateTime.now());
|
||||
orderInfo.setUpdateTime(LocalDateTime.now());
|
||||
orderInfo.setIsDeleted(0);
|
||||
|
||||
orderInfoMapper.insert(orderInfo);
|
||||
|
||||
// 4. 创建订单项记录
|
||||
for (ShoppingCart cart : cartList) {
|
||||
ProductSku sku = productSkuMapper.selectById(cart.getSkuId());
|
||||
Product product = productMapper.selectById(cart.getProductId());
|
||||
|
||||
OrderItem orderItem = new OrderItem();
|
||||
orderItem.setOrderId(orderInfo.getId());
|
||||
orderItem.setOrderNo(orderNo);
|
||||
orderItem.setProductId(cart.getProductId());
|
||||
orderItem.setSkuId(cart.getSkuId());
|
||||
orderItem.setProductName(product.getName());
|
||||
orderItem.setSkuName(sku.getSkuName());
|
||||
orderItem.setProductImage(product.getMainImage());
|
||||
orderItem.setPrice(sku.getPrice());
|
||||
orderItem.setQuantity(cart.getCount());
|
||||
orderItem.setTotalPrice(sku.getPrice().multiply(new BigDecimal(cart.getCount())));
|
||||
orderItem.setCreateTime(LocalDateTime.now());
|
||||
orderItem.setUpdateTime(LocalDateTime.now());
|
||||
orderItem.setIsDeleted(0);
|
||||
|
||||
orderItemMapper.insert(orderItem);
|
||||
|
||||
// 5. 扣减库存
|
||||
sku.setStock(sku.getStock() - cart.getCount());
|
||||
productSkuMapper.updateById(sku);
|
||||
}
|
||||
|
||||
// 6. 清空购物车中已下单的商品
|
||||
shoppingCartMapper.delete(queryWrapper);
|
||||
|
||||
log.info("创建订单成功: {}", orderNo);
|
||||
return orderInfo.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<OrderListVO> getOrderPage(Integer page, Integer size, Long userId, Integer status) {
|
||||
// 构造查询条件
|
||||
QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("is_deleted", 0); // 排除逻辑删除的记录
|
||||
|
||||
if (userId != null) {
|
||||
queryWrapper.eq("user_id", userId);
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
queryWrapper.eq("status", status);
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc("create_time");
|
||||
|
||||
// 使用MyBatis-Plus分页查询
|
||||
Page<OrderInfo> pageInfo = new Page<>(page, size);
|
||||
Page<OrderInfo> orderPage = orderInfoMapper.selectPage(pageInfo, queryWrapper);
|
||||
|
||||
// 转换为VO对象
|
||||
Page<OrderListVO> voPage = new Page<>(page, size, orderPage.getTotal());
|
||||
List<OrderListVO> voList = orderPage.getRecords().stream().map(orderInfo -> {
|
||||
OrderListVO vo = new OrderListVO();
|
||||
BeanUtils.copyProperties(orderInfo, vo);
|
||||
QueryWrapper<OrderItem> itemQueryWrapper = new QueryWrapper<>();
|
||||
itemQueryWrapper.eq("order_id", orderInfo.getId());
|
||||
List<OrderItem> itemList = orderItemMapper.selectList(itemQueryWrapper);
|
||||
Integer count = 0;
|
||||
for (OrderItem item : itemList) {
|
||||
count += item.getQuantity();
|
||||
}
|
||||
vo.setProductCount(count);
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
voPage.setRecords(voList);
|
||||
|
||||
// 转换状态码为文本
|
||||
voPage.getRecords().forEach(vo -> {
|
||||
switch (vo.getStatus()) {
|
||||
case 0: vo.setStatusText("待付款"); break;
|
||||
case 1: vo.setStatusText("待发货"); break;
|
||||
case 2: vo.setStatusText("待收货"); break;
|
||||
case 3: vo.setStatusText("已完成"); break;
|
||||
case 4: vo.setStatusText("已取消"); break;
|
||||
default: vo.setStatusText("未知状态");
|
||||
}
|
||||
});
|
||||
|
||||
return voPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderVO getOrderDetail(Long orderId, Long userId) {
|
||||
// 查询订单主信息
|
||||
OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
|
||||
if (orderInfo == null || orderInfo.getIsDeleted() == 1) {
|
||||
throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 验证订单归属
|
||||
if (!orderInfo.getUserId().equals(userId)) {
|
||||
throw new BusinessException(MessageConstant.NO_PERMISSION);
|
||||
}
|
||||
|
||||
// 查询订单项
|
||||
LambdaQueryWrapper<OrderItem> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(OrderItem::getOrderId, orderId)
|
||||
.eq(OrderItem::getIsDeleted, 0);
|
||||
List<OrderItem> orderItems = orderItemMapper.selectList(queryWrapper);
|
||||
|
||||
// 转换为VO
|
||||
OrderVO orderVO = new OrderVO();
|
||||
BeanUtils.copyProperties(orderInfo, orderVO);
|
||||
orderVO.setOrderItems(orderItems);
|
||||
|
||||
return orderVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateOrderStatus(OrderStatusDTO statusDTO) {
|
||||
QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("id", statusDTO.getOrderId())
|
||||
.eq("is_deleted", 0);
|
||||
OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);
|
||||
// 验证状态转换的合法性
|
||||
Integer currentStatus = orderInfo.getStatus();
|
||||
Integer newStatus = statusDTO.getStatus();
|
||||
|
||||
// 状态转换规则校验
|
||||
if (!isValidStatusTransition(currentStatus, newStatus)) {
|
||||
throw new BusinessException("不允许从状态 " + currentStatus + " 转换到 " + newStatus);
|
||||
}
|
||||
|
||||
// 更新状态和相关时间
|
||||
orderInfo.setStatus(newStatus);
|
||||
orderInfo.setUpdateTime(LocalDateTime.now());
|
||||
|
||||
// 根据状态设置相应的时间
|
||||
if (newStatus == 1) { // 待发货 -> 支付时间
|
||||
orderInfo.setPayTime(LocalDateTime.now());
|
||||
} else if (newStatus == 2) { // 待收货 -> 发货时间
|
||||
orderInfo.setDeliveryTime(LocalDateTime.now());
|
||||
} else if (newStatus == 3) { // 已完成 -> 收货时间
|
||||
orderInfo.setReceiveTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
orderInfoMapper.updateById(orderInfo);
|
||||
log.info("订单 {} 状态更新为: {}", orderInfo.getOrderNo(), newStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证状态转换是否合法
|
||||
*/
|
||||
private boolean isValidStatusTransition(Integer currentStatus, Integer newStatus) {
|
||||
// 状态转换规则:
|
||||
// 0-待付款 -> 1-待发货 或 4-已取消
|
||||
// 1-待发货 -> 2-待收货 或 4-已取消
|
||||
// 2-待收货 -> 3-已完成 或 4-已取消
|
||||
// 3-已完成 -> 不能转换
|
||||
// 4-已取消 -> 不能转换
|
||||
|
||||
if (currentStatus == 0) {
|
||||
return newStatus == 1 || newStatus == 4;
|
||||
} else if (currentStatus == 1) {
|
||||
return newStatus == 2 || newStatus == 4;
|
||||
} else if (currentStatus == 2) {
|
||||
return newStatus == 3 || newStatus == 4;
|
||||
} else { // 3或4状态不能再转换
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// UserAddressServiceImpl.java
|
||||
package icu.sunway.ai_spring_example.Service.Impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import icu.sunway.ai_spring_example.Common.Exception.BusinessException;
|
||||
import icu.sunway.ai_spring_example.Common.Constant.MessageConstant;
|
||||
import icu.sunway.ai_spring_example.Mapper.UserAddressMapper;
|
||||
import icu.sunway.ai_spring_example.Service.UserAddressService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddress> implements UserAddressService {
|
||||
|
||||
private final UserAddressMapper userAddressMapper;
|
||||
|
||||
public UserAddressServiceImpl(UserAddressMapper userAddressMapper) {
|
||||
this.userAddressMapper = userAddressMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void addAddress(UserAddressDTO addressDTO) {
|
||||
log.info("新增用户地址: {}", addressDTO);
|
||||
UserAddress address = new UserAddress();
|
||||
BeanUtils.copyProperties(addressDTO, address);
|
||||
|
||||
// 如果设置为默认地址,先取消该用户其他默认地址
|
||||
if (address.getIsDefault() != null && address.getIsDefault() == 1) {
|
||||
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserAddress::getUserId, address.getUserId())
|
||||
.eq(UserAddress::getIsDefault, 1);
|
||||
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
|
||||
if (defaultAddress != null) {
|
||||
defaultAddress.setIsDefault(0);
|
||||
userAddressMapper.updateById(defaultAddress);
|
||||
}
|
||||
} else {
|
||||
// 如果是首次添加地址,默认设为默认地址
|
||||
LambdaQueryWrapper<UserAddress> countWrapper = new LambdaQueryWrapper<>();
|
||||
countWrapper.eq(UserAddress::getUserId, address.getUserId());
|
||||
long count = userAddressMapper.selectCount(countWrapper);
|
||||
if (count == 0) {
|
||||
address.setIsDefault(1);
|
||||
} else {
|
||||
address.setIsDefault(0); // 非首次添加且未指定默认,设为非默认
|
||||
}
|
||||
}
|
||||
|
||||
userAddressMapper.insert(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateAddress(UserAddressDTO addressDTO) {
|
||||
log.info("更新用户地址: {}", addressDTO);
|
||||
if (addressDTO.getId() == null) {
|
||||
throw new BusinessException(MessageConstant.ADDRESS_ID_NULL);
|
||||
}
|
||||
|
||||
// 验证地址是否存在且属于当前用户
|
||||
UserAddress address = userAddressMapper.selectById(addressDTO.getId());
|
||||
if (address == null || !address.getUserId().equals(addressDTO.getUserId())) {
|
||||
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
|
||||
}
|
||||
|
||||
BeanUtils.copyProperties(addressDTO, address);
|
||||
|
||||
// 如果设置为默认地址,先取消该用户其他默认地址
|
||||
if (address.getIsDefault() != null && address.getIsDefault() == 1) {
|
||||
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserAddress::getUserId, address.getUserId())
|
||||
.eq(UserAddress::getIsDefault, 1)
|
||||
.ne(UserAddress::getId, address.getId()); // 排除当前地址
|
||||
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
|
||||
if (defaultAddress != null) {
|
||||
defaultAddress.setIsDefault(0);
|
||||
userAddressMapper.updateById(defaultAddress);
|
||||
}
|
||||
}
|
||||
|
||||
address.setUpdateTime(LocalDateTime.now());
|
||||
userAddressMapper.updateById(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteAddress(Long id, Long userId) {
|
||||
log.info("删除用户地址: id={}, userId={}", id, userId);
|
||||
if (id == null || userId == null) {
|
||||
throw new BusinessException(MessageConstant.PARAM_ERROR);
|
||||
}
|
||||
|
||||
UserAddress address = userAddressMapper.selectById(id);
|
||||
if (address == null || !address.getUserId().equals(userId)) {
|
||||
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 如果删除的是默认地址,需要将其他地址设为默认
|
||||
if (address.getIsDefault() == 1) {
|
||||
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserAddress::getUserId, userId)
|
||||
.ne(UserAddress::getId, id)
|
||||
.eq(UserAddress::getIsDeleted, 0);
|
||||
List<UserAddress> otherAddresses = userAddressMapper.selectList(queryWrapper);
|
||||
if (!otherAddresses.isEmpty()) {
|
||||
UserAddress newDefault = otherAddresses.get(0);
|
||||
newDefault.setIsDefault(1);
|
||||
userAddressMapper.updateById(newDefault);
|
||||
}
|
||||
}
|
||||
|
||||
// 逻辑删除
|
||||
QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("id", id);
|
||||
userAddressMapper.delete(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserAddress> getAddressListByUserId(Long userId) {
|
||||
log.info("查询用户地址列表: userId={}", userId);
|
||||
if (userId == null) {
|
||||
throw new BusinessException(MessageConstant.PARAM_ERROR);
|
||||
}
|
||||
QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
|
||||
return userAddressMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAddress getAddressById(Long id, Long userId) {
|
||||
log.info("查询地址详情: id={}, userId={}", id, userId);
|
||||
if (id == null || userId == null) {
|
||||
throw new BusinessException(MessageConstant.PARAM_ERROR);
|
||||
}
|
||||
|
||||
UserAddress address = userAddressMapper.selectById(id);
|
||||
if (address == null || address.getIsDeleted() == 1 || !address.getUserId().equals(userId)) {
|
||||
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void setDefaultAddress(Long id, Long userId) {
|
||||
log.info("设置默认地址: id={}, userId={}", id, userId);
|
||||
if (id == null || userId == null) {
|
||||
throw new BusinessException(MessageConstant.PARAM_ERROR);
|
||||
}
|
||||
|
||||
// 验证地址是否存在且属于当前用户
|
||||
UserAddress address = userAddressMapper.selectById(id);
|
||||
if (address == null || address.getIsDeleted() == 1 || !address.getUserId().equals(userId)) {
|
||||
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 取消其他默认地址
|
||||
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserAddress::getUserId, userId)
|
||||
.eq(UserAddress::getIsDefault, 1)
|
||||
.ne(UserAddress::getId, id);
|
||||
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
|
||||
if (defaultAddress != null) {
|
||||
defaultAddress.setIsDefault(0);
|
||||
userAddressMapper.updateById(defaultAddress);
|
||||
}
|
||||
|
||||
// 设置当前地址为默认
|
||||
address.setIsDefault(1);
|
||||
address.setUpdateTime(LocalDateTime.now());
|
||||
userAddressMapper.updateById(address);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// OrderService.java
|
||||
package icu.sunway.ai_spring_example.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.OrderInfo;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
|
||||
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
|
||||
|
||||
public interface OrderService extends IService<OrderInfo> {
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
* @param orderDTO 订单信息
|
||||
* @return 订单ID
|
||||
*/
|
||||
Long createOrder(OrderDTO orderDTO);
|
||||
|
||||
/**
|
||||
* 分页查询订单列表
|
||||
* @param page 页码
|
||||
* @param size 每页条数
|
||||
* @param userId 用户ID
|
||||
* @param status 订单状态
|
||||
* @return 订单列表
|
||||
*/
|
||||
Page<OrderListVO> getOrderPage(Integer page, Integer size, Long userId, Integer status);
|
||||
|
||||
/**
|
||||
* 查询订单详情
|
||||
* @param orderId 订单ID
|
||||
* @param userId 用户ID
|
||||
* @return 订单详情
|
||||
*/
|
||||
OrderVO getOrderDetail(Long orderId, Long userId);
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
* @param statusDTO 订单状态信息
|
||||
*/
|
||||
void updateOrderStatus(OrderStatusDTO statusDTO);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// UserAddressService.java
|
||||
package icu.sunway.ai_spring_example.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserAddressService extends IService<UserAddress> {
|
||||
|
||||
/**
|
||||
* 添加用户地址
|
||||
* @param addressDTO 地址信息
|
||||
*/
|
||||
void addAddress(UserAddressDTO addressDTO);
|
||||
|
||||
/**
|
||||
* 更新用户地址
|
||||
* @param addressDTO 地址信息
|
||||
*/
|
||||
void updateAddress(UserAddressDTO addressDTO);
|
||||
|
||||
/**
|
||||
* 删除用户地址
|
||||
* @param id 地址ID
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void deleteAddress(Long id, Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询地址列表
|
||||
* @param userId 用户ID
|
||||
* @return 地址列表
|
||||
*/
|
||||
List<UserAddress> getAddressListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据地址ID查询地址详情
|
||||
* @param id 地址ID
|
||||
* @param userId 用户ID
|
||||
* @return 地址详情
|
||||
*/
|
||||
UserAddress getAddressById(Long id, Long userId);
|
||||
|
||||
/**
|
||||
* 设置默认地址
|
||||
* @param id 地址ID
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void setDefaultAddress(Long id, Long userId);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// OrderDTO.java
|
||||
package icu.sunway.ai_spring_example.pojo.Dto;
|
||||
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class OrderDTO {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 收货人姓名
|
||||
*/
|
||||
@NotBlank(message = "收货人姓名不能为空")
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 收货人手机号
|
||||
*/
|
||||
@NotBlank(message = "收货人手机号不能为空")
|
||||
private String receiverPhone;
|
||||
|
||||
/**
|
||||
* 收货人地址
|
||||
*/
|
||||
@NotBlank(message = "收货人地址不能为空")
|
||||
private String receiverAddress;
|
||||
|
||||
/**
|
||||
* 支付方式 0-未支付 1-微信 2-支付宝
|
||||
*/
|
||||
private Integer payType = 0;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// OrderStatusDTO.java
|
||||
package icu.sunway.ai_spring_example.pojo.Dto;
|
||||
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class OrderStatusDTO {
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@NotNull(message = "订单ID不能为空")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
|
||||
*/
|
||||
@NotNull(message = "订单状态不能为空")
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// UserAddressDTO.java
|
||||
package icu.sunway.ai_spring_example.pojo.Dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserAddressDTO {
|
||||
private Long id; // 地址ID,新增时可不传,修改时必传
|
||||
|
||||
@NotNull(message = "用户ID不能为空")
|
||||
private Long userId; // 用户ID
|
||||
|
||||
@NotBlank(message = "收货人姓名不能为空")
|
||||
private String receiverName; // 收货人姓名
|
||||
|
||||
@NotBlank(message = "收货人手机号不能为空")
|
||||
private String receiverPhone; // 收货人手机号
|
||||
|
||||
@NotBlank(message = "省份不能为空")
|
||||
private String province; // 省
|
||||
|
||||
@NotBlank(message = "城市不能为空")
|
||||
private String city; // 市
|
||||
|
||||
@NotBlank(message = "区县不能为空")
|
||||
private String district; // 区/县
|
||||
|
||||
@NotBlank(message = "详细地址不能为空")
|
||||
private String detailAddress; // 详细地址
|
||||
|
||||
private Integer isDefault; // 是否默认(0-非默认,1-默认)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import java.time.LocalDateTime;
|
||||
/**
|
||||
* 用户地址表实体类
|
||||
*
|
||||
* @author ZhiWei
|
||||
* @author PuZhiWei
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@Data
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// OrderListVO.java
|
||||
package icu.sunway.ai_spring_example.pojo.Vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class OrderListVO {
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 订单总金额
|
||||
*/
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/**
|
||||
* 实付金额
|
||||
*/
|
||||
private BigDecimal payAmount;
|
||||
|
||||
/**
|
||||
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 订单状态文本
|
||||
*/
|
||||
private String statusText;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 商品数量
|
||||
*/
|
||||
private Integer productCount;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// OrderVO.java
|
||||
package icu.sunway.ai_spring_example.pojo.Vo;
|
||||
|
||||
import icu.sunway.ai_spring_example.pojo.Entity.OrderItem;
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OrderVO {
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 订单总金额
|
||||
*/
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/**
|
||||
* 实付金额
|
||||
*/
|
||||
private BigDecimal payAmount;
|
||||
|
||||
/**
|
||||
* 运费
|
||||
*/
|
||||
private BigDecimal freightAmount;
|
||||
|
||||
/**
|
||||
* 支付方式 0-未支付 1-微信 2-支付宝
|
||||
*/
|
||||
private Integer payType;
|
||||
|
||||
/**
|
||||
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 收货人信息
|
||||
*/
|
||||
private String receiverName;
|
||||
private String receiverPhone;
|
||||
private String receiverAddress;
|
||||
|
||||
/**
|
||||
* 时间信息
|
||||
*/
|
||||
private LocalDateTime payTime;
|
||||
private LocalDateTime deliveryTime;
|
||||
private LocalDateTime receiveTime;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 订单项列表
|
||||
*/
|
||||
private List<OrderItem> orderItems;
|
||||
}
|
||||
Reference in New Issue
Block a user