优化下单流程
This commit is contained in:
248
docs/backend-order-service-example.java
Normal file
248
docs/backend-order-service-example.java
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* 订单服务实现类示例
|
||||
* 展示如何保存订单商品信息的业务逻辑
|
||||
*/
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ShopOrderServiceImpl implements ShopOrderService {
|
||||
|
||||
@Autowired
|
||||
private ShopOrderMapper shopOrderMapper;
|
||||
|
||||
@Autowired
|
||||
private OrderGoodsMapper orderGoodsMapper;
|
||||
|
||||
@Autowired
|
||||
private ShopGoodsService shopGoodsService;
|
||||
|
||||
@Autowired
|
||||
private ShopUserAddressService addressService;
|
||||
|
||||
@Autowired
|
||||
private WxPayService wxPayService;
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, String> createOrder(OrderCreateRequest request, User loginUser) {
|
||||
// 1. 参数校验
|
||||
validateOrderRequest(request, loginUser);
|
||||
|
||||
// 2. 构建订单对象
|
||||
ShopOrder shopOrder = buildShopOrder(request, loginUser);
|
||||
|
||||
// 3. 应用业务规则
|
||||
applyBusinessRules(shopOrder, loginUser);
|
||||
|
||||
// 4. 保存订单主表
|
||||
boolean saved = shopOrderMapper.insert(shopOrder) > 0;
|
||||
if (!saved) {
|
||||
throw new BusinessException("订单保存失败");
|
||||
}
|
||||
|
||||
// 5. 保存订单商品明细 - 核心业务逻辑
|
||||
saveOrderGoods(shopOrder, request.getGoodsItems());
|
||||
|
||||
// 6. 创建微信支付订单
|
||||
try {
|
||||
return wxPayService.createWxOrder(shopOrder);
|
||||
} catch (Exception e) {
|
||||
log.error("创建微信支付订单失败,订单号:{}", shopOrder.getOrderNo(), e);
|
||||
throw new BusinessException("创建支付订单失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存订单商品明细 - 核心实现
|
||||
*/
|
||||
private void saveOrderGoods(ShopOrder shopOrder, List<OrderGoodsItem> goodsItems) {
|
||||
List<OrderGoods> orderGoodsList = new ArrayList<>();
|
||||
BigDecimal totalPrice = BigDecimal.ZERO;
|
||||
int totalQuantity = 0;
|
||||
List<String> goodsNames = new ArrayList<>();
|
||||
|
||||
for (OrderGoodsItem item : goodsItems) {
|
||||
// 1. 获取商品最新信息进行校验
|
||||
ShopGoods goods = shopGoodsService.getById(item.getGoodsId());
|
||||
if (goods == null) {
|
||||
throw new BusinessException("商品不存在:" + item.getGoodsId());
|
||||
}
|
||||
|
||||
// 2. 商品状态校验
|
||||
if (goods.getIsShow() != 1) {
|
||||
throw new BusinessException("商品已下架:" + goods.getName());
|
||||
}
|
||||
|
||||
// 3. 库存校验
|
||||
if (goods.getStock() < item.getQuantity()) {
|
||||
throw new BusinessException("商品库存不足:" + goods.getName());
|
||||
}
|
||||
|
||||
// 4. 价格计算(以数据库中的价格为准)
|
||||
BigDecimal itemPrice = new BigDecimal(goods.getPrice());
|
||||
BigDecimal itemTotalPrice = itemPrice.multiply(new BigDecimal(item.getQuantity()));
|
||||
|
||||
// 5. 构建订单商品记录
|
||||
OrderGoods orderGoods = new OrderGoods();
|
||||
orderGoods.setOrderId(shopOrder.getOrderId());
|
||||
orderGoods.setGoodsId(item.getGoodsId());
|
||||
orderGoods.setTotalNum(item.getQuantity());
|
||||
orderGoods.setPayPrice(itemTotalPrice.toString());
|
||||
orderGoods.setType(0); // 0商城
|
||||
orderGoods.setPayStatus("0"); // 0未付款
|
||||
orderGoods.setOrderStatus(0); // 0未完成
|
||||
orderGoods.setUserId(shopOrder.getUserId());
|
||||
orderGoods.setTenantId(shopOrder.getTenantId());
|
||||
orderGoods.setCreateTime(LocalDateTime.now());
|
||||
|
||||
// 6. SKU信息处理(如果有规格)
|
||||
if (item.getSkuId() != null) {
|
||||
// 处理SKU相关逻辑
|
||||
// orderGoods.setSkuId(item.getSkuId());
|
||||
// orderGoods.setSpecInfo(item.getSpecInfo());
|
||||
}
|
||||
|
||||
orderGoodsList.add(orderGoods);
|
||||
|
||||
// 7. 累计计算
|
||||
totalPrice = totalPrice.add(itemTotalPrice);
|
||||
totalQuantity += item.getQuantity();
|
||||
goodsNames.add(goods.getName());
|
||||
|
||||
// 8. 扣减库存(根据业务需求,可能在支付成功后扣减)
|
||||
if (goods.getDeductStockType() == 10) { // 10下单减库存
|
||||
goods.setStock(goods.getStock() - item.getQuantity());
|
||||
shopGoodsService.updateById(goods);
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 批量保存订单商品
|
||||
if (!orderGoodsList.isEmpty()) {
|
||||
orderGoodsMapper.insertBatch(orderGoodsList);
|
||||
}
|
||||
|
||||
// 10. 更新订单总价和数量
|
||||
shopOrder.setTotalPrice(totalPrice.toString());
|
||||
shopOrder.setPayPrice(totalPrice.toString()); // 暂时不考虑优惠
|
||||
shopOrder.setTotalNum(totalQuantity);
|
||||
|
||||
// 11. 生成订单标题(限制30个汉字)
|
||||
String title = generateOrderTitle(goodsNames);
|
||||
shopOrder.setTitle(title);
|
||||
|
||||
// 12. 更新订单主表
|
||||
shopOrderMapper.updateById(shopOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单标题,限制长度不超过30个汉字
|
||||
*/
|
||||
private String generateOrderTitle(List<String> goodsNames) {
|
||||
if (goodsNames.isEmpty()) {
|
||||
return "商品订单";
|
||||
}
|
||||
|
||||
String title;
|
||||
if (goodsNames.size() == 1) {
|
||||
title = goodsNames.get(0);
|
||||
} else {
|
||||
title = goodsNames.get(0) + "等" + goodsNames.size() + "件商品";
|
||||
}
|
||||
|
||||
// 限制标题长度最多30个汉字
|
||||
if (title.length() > 30) {
|
||||
title = title.substring(0, 30);
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数校验
|
||||
*/
|
||||
private void validateOrderRequest(OrderCreateRequest request, User loginUser) {
|
||||
if (request.getGoodsItems() == null || request.getGoodsItems().isEmpty()) {
|
||||
throw new BusinessException("商品信息不能为空");
|
||||
}
|
||||
|
||||
if (request.getAddressId() == null) {
|
||||
throw new BusinessException("收货地址不能为空");
|
||||
}
|
||||
|
||||
// 校验收货地址是否属于当前用户
|
||||
ShopUserAddress address = addressService.getById(request.getAddressId());
|
||||
if (address == null || !address.getUserId().equals(loginUser.getUserId())) {
|
||||
throw new BusinessException("收货地址不存在或不属于当前用户");
|
||||
}
|
||||
|
||||
// 校验商品数量
|
||||
for (OrderGoodsItem item : request.getGoodsItems()) {
|
||||
if (item.getGoodsId() == null || item.getQuantity() <= 0) {
|
||||
throw new BusinessException("商品信息不正确");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建订单对象
|
||||
*/
|
||||
private ShopOrder buildShopOrder(OrderCreateRequest request, User loginUser) {
|
||||
ShopOrder shopOrder = new ShopOrder();
|
||||
|
||||
// 基础信息
|
||||
shopOrder.setOrderNo(generateOrderNo());
|
||||
shopOrder.setType(0); // 0商城订单
|
||||
shopOrder.setChannel(0); // 0小程序
|
||||
shopOrder.setUserId(loginUser.getUserId());
|
||||
shopOrder.setTenantId(loginUser.getTenantId());
|
||||
|
||||
// 用户信息
|
||||
shopOrder.setRealName(loginUser.getRealName());
|
||||
shopOrder.setPhone(loginUser.getPhone());
|
||||
|
||||
// 地址信息
|
||||
ShopUserAddress address = addressService.getById(request.getAddressId());
|
||||
shopOrder.setAddressId(request.getAddressId());
|
||||
shopOrder.setAddress(address.getProvince() + address.getCity() +
|
||||
address.getRegion() + address.getAddress());
|
||||
|
||||
// 支付信息
|
||||
shopOrder.setPayType(request.getPayType());
|
||||
shopOrder.setPayStatus(0); // 0未付款
|
||||
shopOrder.setOrderStatus(0); // 0未使用
|
||||
|
||||
// 配送信息
|
||||
shopOrder.setDeliveryType(request.getDeliveryType());
|
||||
if (request.getSelfTakeMerchantId() != null) {
|
||||
shopOrder.setSelfTakeMerchantId(request.getSelfTakeMerchantId());
|
||||
}
|
||||
|
||||
// 其他信息
|
||||
shopOrder.setComments(request.getComments());
|
||||
shopOrder.setCreateTime(LocalDateTime.now());
|
||||
|
||||
return shopOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用业务规则
|
||||
*/
|
||||
private void applyBusinessRules(ShopOrder shopOrder, User loginUser) {
|
||||
// 设置默认标题(如果没有设置)
|
||||
if (shopOrder.getTitle() == null) {
|
||||
shopOrder.setTitle("商品订单");
|
||||
}
|
||||
|
||||
// 其他业务规则...
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单号
|
||||
*/
|
||||
private String generateOrderNo() {
|
||||
return "SO" + System.currentTimeMillis() +
|
||||
String.format("%04d", new Random().nextInt(10000));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user