一、功能概述
组合套餐销售是美团买菜系统中提升客单价、促进商品销售的重要功能,允许商家将多个商品打包销售,通常以优惠价格吸引用户购买。
二、系统架构设计
1. 数据库设计
套餐表(combo)
```
id (主键)
name (套餐名称)
description (描述)
original_price (原价总和)
discount_price (套餐价)
start_time (开始时间)
end_time (结束时间)
status (状态:上架/下架)
image_url (图片)
```
套餐商品关联表(combo_items)
```
id (主键)
combo_id (套餐ID)
product_id (商品ID)
quantity (数量)
sort_order (排序)
```
用户购买记录表(combo_orders)
```
id (主键)
user_id (用户ID)
combo_id (套餐ID)
order_id (关联订单ID)
create_time (购买时间)
```
2. 核心模块划分
1. 套餐管理模块
- 套餐创建、编辑、上下架
- 套餐商品配置
- 价格计算规则
2. 前端展示模块
- 套餐列表页
- 套餐详情页
- 购物车集成
3. 订单处理模块
- 套餐库存校验
- 订单拆分处理
- 价格计算
4. 营销活动模块
- 套餐限时折扣
- 满减组合
- 新人专享套餐
三、关键功能实现
1. 套餐创建流程
```java
// 后端套餐创建示例
public Combo createCombo(ComboDTO comboDTO) {
// 1. 校验商品是否存在
List
products = productService.batchGetByIds(comboDTO.getProductIds());
if (products.size() != comboDTO.getProductIds().size()) {
throw new BusinessException("部分商品不存在");
}
// 2. 计算原价总和
BigDecimal originalPrice = BigDecimal.ZERO;
for (Product product : products) {
originalPrice = originalPrice.add(product.getPrice().multiply(
new BigDecimal(comboDTO.getQuantities().get(product.getId()))));
}
// 3. 校验套餐价是否低于原价
if (comboDTO.getDiscountPrice().compareTo(originalPrice) >= 0) {
throw new BusinessException("套餐价必须低于原价总和");
}
// 4. 保存套餐信息
Combo combo = new Combo();
combo.setName(comboDTO.getName());
combo.setOriginalPrice(originalPrice);
combo.setDiscountPrice(comboDTO.getDiscountPrice());
// ...其他字段设置
comboRepository.save(combo);
// 5. 保存套餐商品关联
for (Map.Entry entry : comboDTO.getQuantities().entrySet()) {
ComboItem item = new ComboItem();
item.setComboId(combo.getId());
item.setProductId(entry.getKey());
item.setQuantity(entry.getValue());
comboItemRepository.save(item);
}
return combo;
}
```
2. 前端展示逻辑
```javascript
// React套餐组件示例
function ComboCard({ combo }) {
const [showDetail, setShowDetail] = useState(false);
return (
{combo.name}
¥{combo.discountPrice}
¥{combo.originalPrice}
{showDetail && (
{combo.items.map(item => (
{item.productName} × {item.quantity}
))}
)}
);
}
```
3. 购物车集成
```java
// 购物车服务中添加套餐
public Cart addComboToCart(Long userId, Long comboId, int quantity) {
Combo combo = comboRepository.findByIdAndStatus(comboId, ComboStatus.ONLINE)
.orElseThrow(() -> new BusinessException("套餐不存在或已下架"));
// 检查套餐是否在有效期内
if (LocalDateTime.now().isBefore(combo.getStartTime()) ||
LocalDateTime.now().isAfter(combo.getEndTime())) {
throw new BusinessException("套餐不在销售期内");
}
// 检查套餐库存(需要实现)
// 添加到购物车
CartItem cartItem = new CartItem();
cartItem.setUserId(userId);
cartItem.setComboId(comboId);
cartItem.setQuantity(quantity);
cartItem.setPrice(combo.getDiscountPrice());
// ...其他字段
cartItemRepository.save(cartItem);
// 更新购物车总价等
return updateCartTotal(userId);
}
```
4. 订单处理
```java
// 订单创建时处理套餐
public Order createOrder(OrderDTO orderDTO) {
Order order = new Order();
// ...基本订单信息设置
BigDecimal totalAmount = BigDecimal.ZERO;
List orderItems = new ArrayList<>();
for (CartItem cartItem : orderDTO.getCartItems()) {
if (cartItem.getComboId() != null) {
// 处理套餐
Combo combo = comboRepository.findById(cartItem.getComboId())
.orElseThrow(() -> new BusinessException("套餐不存在"));
// 扣减套餐中各商品的库存
List comboItems = comboItemRepository.findByComboId(combo.getId());
for (ComboItem comboItem : comboItems) {
Product product = productRepository.findById(comboItem.getProductId())
.orElseThrow(() -> new BusinessException("商品不存在"));
// 库存校验和扣减
if (product.getStock() < comboItem.getQuantity() * cartItem.getQuantity()) {
throw new BusinessException(product.getName() + "库存不足");
}
product.setStock(product.getStock() - comboItem.getQuantity() * cartItem.getQuantity());
productRepository.save(product);
// 添加订单项
OrderItem orderItem = new OrderItem();
orderItem.setProductId(product.getId());
orderItem.setProductName(product.getName());
orderItem.setPrice(product.getPrice());
orderItem.setQuantity(comboItem.getQuantity() * cartItem.getQuantity());
orderItems.add(orderItem);
}
totalAmount = totalAmount.add(combo.getDiscountPrice().multiply(
new BigDecimal(cartItem.getQuantity())));
} else {
// 处理普通商品...
}
}
order.setTotalAmount(totalAmount);
order.setOrderItems(orderItems);
// ...保存订单
return order;
}
```
四、关键技术点
1. 库存管理
- 套餐销售需要同时扣减多个商品的库存
- 采用分布式锁防止超卖
- 实现库存预占机制
2. 价格计算
- 套餐价与原价对比展示
- 多级价格计算(如会员价、新人价等)
- 避免浮点数精度问题,使用BigDecimal
3. 有效期管理
- 套餐的起止时间控制
- 定时任务检查过期套餐
4. 性能优化
- 套餐商品信息缓存
- 热门套餐预加载
- 数据库索引优化
五、测试要点
1. 功能测试
- 套餐创建、编辑、删除
- 套餐上下架
- 套餐加入购物车
- 订单生成与支付
2. 边界测试
- 库存不足时的处理
- 套餐过期时的处理
- 商品下架后的套餐处理
3. 性能测试
- 高并发下套餐购买
- 大量套餐数据查询
4. 兼容性测试
- 不同终端显示效果
- 不同支付方式集成
六、部署与监控
1. 部署方案
- 套餐服务独立部署或与商品服务合并
- 配置中心管理套餐相关参数
2. 监控指标
- 套餐购买转化率
- 套餐库存预警
- 套餐访问热度
3. 日志收集
- 套餐操作日志
- 库存变更日志
- 订单处理日志
通过以上方案,美团买菜系统可以实现高效、稳定的组合套餐销售功能,提升用户体验和平台销售额。