一、功能概述
组合套餐销售是美团买菜系统中重要的营销功能,允许商家将多个商品打包销售,提供价格优惠,提升客单价和用户购买意愿。该功能需要实现套餐创建、展示、购买和订单处理等全流程支持。
二、系统架构设计
1. 前端模块
- 套餐展示页面:展示套餐图片、包含商品、原价与套餐价对比
- 套餐选择组件:支持用户选择套餐规格(如不同份数)
- 购物车集成:套餐作为特殊商品类型加入购物车
- 结算页面:显示套餐优惠信息和最终价格
2. 后端服务
- 套餐管理服务:套餐CRUD操作、上下架管理
- 商品关联服务:建立套餐与商品的关联关系
- 价格计算服务:实时计算套餐价格和优惠
- 库存服务:处理套餐库存与单品库存的联动
3. 数据库设计
```sql
-- 套餐主表
CREATE TABLE meal_package (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
description TEXT,
original_price DECIMAL(10,2) NOT NULL,
package_price DECIMAL(10,2) NOT NULL,
discount_rate DECIMAL(5,2),
status TINYINT DEFAULT 1 COMMENT 1-上架 0-下架,
create_time DATETIME,
update_time DATETIME
);
-- 套餐商品关联表
CREATE TABLE package_items (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
package_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
create_time DATETIME,
FOREIGN KEY (package_id) REFERENCES meal_package(id),
FOREIGN KEY (product_id) REFERENCES product(id)
);
-- 套餐库存表(可选)
CREATE TABLE package_stock (
package_id BIGINT,
stock_quantity INT DEFAULT 0,
sold_quantity INT DEFAULT 0,
update_time DATETIME,
PRIMARY KEY (package_id)
);
```
三、核心功能实现
1. 套餐创建流程
```java
public class PackageService {
public boolean createPackage(PackageDTO packageDTO) {
// 1. 验证商品是否存在
List
productIds = packageDTO.getProductIds();
if (!productService.checkAllExist(productIds)) {
throw new BusinessException("部分商品不存在");
}
// 2. 计算套餐价格
BigDecimal originalPrice = calculateOriginalPrice(productIds, packageDTO.getQuantities());
if (packageDTO.getPackagePrice().compareTo(originalPrice) >= 0) {
throw new BusinessException("套餐价格必须低于原价");
}
// 3. 保存套餐信息
MealPackage mealPackage = new MealPackage();
// 设置套餐属性...
mealPackageRepository.save(mealPackage);
// 4. 保存套餐商品关联
for (int i = 0; i < productIds.size(); i++) {
PackageItem item = new PackageItem();
item.setPackageId(mealPackage.getId());
item.setProductId(productIds.get(i));
item.setQuantity(quantities.get(i));
packageItemRepository.save(item);
}
return true;
}
private BigDecimal calculateOriginalPrice(List productIds, List quantities) {
BigDecimal total = BigDecimal.ZERO;
for (int i = 0; i < productIds.size(); i++) {
Product product = productService.getById(productIds.get(i));
total = total.add(product.getPrice().multiply(new BigDecimal(quantities.get(i))));
}
return total;
}
}
```
2. 套餐价格计算
```java
public class PriceCalculator {
public BigDecimal calculatePackagePrice(Long packageId, Map productSelections) {
// 获取套餐基础信息
MealPackage package = mealPackageRepository.findById(packageId)
.orElseThrow(() -> new BusinessException("套餐不存在"));
// 计算原价总和
BigDecimal originalTotal = BigDecimal.ZERO;
List items = packageItemRepository.findByPackageId(packageId);
for (PackageItem item : items) {
Product product = productService.getById(item.getProductId());
Integer selectedQty = productSelections.getOrDefault(item.getProductId(), item.getQuantity());
originalTotal = originalTotal.add(product.getPrice().multiply(new BigDecimal(selectedQty)));
}
// 返回套餐价(已包含优惠)
return package.getPackagePrice();
}
}
```
3. 库存管理实现
```java
public class InventoryService {
@Transactional
public boolean reservePackageInventory(Long packageId, int quantity) {
MealPackage mealPackage = mealPackageRepository.findById(packageId)
.orElseThrow(() -> new BusinessException("套餐不存在"));
// 检查套餐库存(如果有独立库存)
if (mealPackage.getStock() != null && mealPackage.getStock() < quantity) {
return false;
}
// 检查各单品库存是否足够
List items = packageItemRepository.findByPackageId(packageId);
for (PackageItem item : items) {
Product product = productService.getById(item.getProductId());
int required = item.getQuantity() * quantity;
if (product.getStock() < required) {
return false;
}
}
// 扣减库存(实际实现中可能需要更复杂的逻辑)
for (PackageItem item : items) {
productService.reduceStock(item.getProductId(), item.getQuantity() * quantity);
}
return true;
}
}
```
四、关键业务规则
1. 价格计算规则:
- 套餐价格必须低于单品总价
- 支持百分比折扣和固定金额折扣
- 显示节省金额和折扣率
2. 库存管理规则:
- 套餐库存可独立设置或基于单品最低库存
- 下单时同时扣减套餐库存和单品库存
- 库存不足时自动下架套餐
3. 展示规则:
- 套餐在搜索结果中优先展示
- 套餐商品不可单独购买(可配置)
- 套餐详情页展示包含商品清单
五、技术挑战与解决方案
1. 库存同步问题:
- 解决方案:使用分布式锁确保库存操作的原子性
- 实现:Redis分布式锁或数据库行锁
2. 价格计算性能:
- 解决方案:缓存套餐价格,异步更新
- 实现:Redis缓存套餐价格,监听商品价格变更事件
3. 套餐变更影响:
- 解决方案:版本控制,变更后生成新套餐ID
- 实现:套餐表增加version字段
六、测试用例设计
1. 功能测试:
- 创建包含多个商品的套餐
- 验证套餐价格计算是否正确
- 测试套餐上下架功能
2. 性能测试:
- 模拟高并发下的套餐购买
- 测试库存扣减的准确性
3. 异常测试:
- 测试商品缺货时的处理
- 测试套餐价格高于原价时的拦截
七、部署与监控
1. 监控指标:
- 套餐购买成功率
- 库存同步延迟
- 价格计算耗时
2. 告警规则:
- 套餐库存不足10%时告警
- 价格计算错误率超过0.1%时告警
3. 日志收集:
- 记录所有套餐操作日志
- 收集用户购买套餐的行为数据
八、扩展功能建议
1. 动态定价:根据库存和需求自动调整套餐价格
2. 个性化推荐:基于用户购买历史推荐套餐
3. 限时抢购:为套餐添加限时优惠功能
4. 社交分享:用户可分享套餐获得额外优惠
通过以上实现方案,美团买菜系统可以构建一个高效、可靠的组合套餐销售功能,提升用户购买体验和平台销售额。