主题
团购 / 拼团 / 套餐 商品业务流程说明文档
版本提示(2026-09-21):本文保留历史流程说明,部分价格模式、固定套餐分摊方式及代码路径已过时。平台运营商品的现行价格规则请参阅《平台运营商品价格逻辑》,不要将下文历史描述直接作为当前实现依据。
本文档用于详细阐述系统中团购(Groupbuy)、**拼团(Pintuan)以及套餐(Package)**商品的整体业务逻辑设计、数据库表结构关系、价格模式规则以及交易结算与下单预约的流转过程,供开发、测试及业务运营人员参考。
一、 核心概念与数据库表设计
在系统设计中,商品的“基础信息”与“营销/价格活动”采用解耦设计,使得同一件商品可以参与不同的营销类型。
1. 核心数据表
- 商品基础表 (
xl_product): 记录商品标题、分类、城市、图片、详情、限购规则、退款类型、扩展属性等基础静态信息。 - 商品活动配置表 (
xl_product_activity): 记录该商品参与的具体活动信息,包括活动类型(团购/拼团/套餐/租赁等)、定价模式(自主定价/底价模式)、平台售价、商户底价、抽成比例、平台加价等。 - 套餐表 (
xl_package): 由平台创建 and 维护的“组合套餐”主表,记录套餐名称、套餐总售价、城市、行程时长、行程介绍等。 - 套餐商品关联表 (
xl_package_item): 将xl_package与商户在xl_product_activity中发布的套餐底价商品进行关联绑定,属于套餐的子项。
2. 实体关联图 (ER Diagram)
二、 价格模式与约束规则
系统中的营销商品区分两种价格模式:
- 自主定价模式 (
self):商户拥有定价权,自己设定销售价,平台按预设的比例对交易额进行扣点抽成。 - 底价模式 (
floor):商户填写结算底价,平台设定最终售价(销售价),底价归商户,溢价部分归平台所有。
1. 不同业务的价格模式限制
活动类型 (activity_type) | 支持的价格模式 (price_mode) | 核心规则约束 |
|---|---|---|
团购 (groupbuy) | 自主定价 (self) / 底价模式 (floor) | 商户可自由选择定价权归属。 |
拼团 (pintuan) | 仅支持底价模式 (floor) | 强制约束,非底价模式保存时会抛出异常。 |
套餐 (package) | 仅支持底价模式 (floor) | 商户发布为底价套餐商品,仅代表结算底价;最终总售价由平台套餐决定。 |
2. 自主定价模式 of 默认抽成比例
在自主定价模式下,若商户未配置抽成比例,系统会采用默认扣点比例:20%。
- 核心代码位置:[
XlProductActivityServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlProductActivityServiceImpl.java) - 业务公式: $$\text{平台抽成 (platformMargin)} = \text{活动售价 (activityPrice)} \times \text{抽成比例 (commissionRate)}$$ 注:若未填抽成比例,系统底层自动在新增时将
commissionRate设为20.00。
3. 微信支付手续费 (0.6%) 共同分摊机制
在所有业务模式下,交易产生的微信支付通道手续费(系统内已从错误的 0.06% 修正为微信支付官方标准的 0.6%)由商户和平台按各自的应得款项比例共同承担,具体结算公式如下:
- 微信支付总手续费: $$\text{总手续费 (totalActualFee)} = \text{用户实际支付售价} \times 0.6%$$
- 商户与平台共同分摊:
- 商户分摊: $$\text{商户手续费分摊} = \text{总手续费} \times \frac{\text{商户应分账金额}}{\text{商品活动售价}}$$ $$\text{商户实际入账可用余额} = \text{商户应分账金额} - \text{商户手续费分摊}$$
- 平台分摊: $$\text{平台手续费分摊} = \text{总手续费} \times \frac{\text{平台应分账金额}}{\text{商品活动售价}}$$ $$\text{平台实际利润所得} = \text{平台应分账金额} - \text{平台手续费分摊}$$
- 注:系统内钱包结算服务底层以“分”为最小计算单元。在计算分摊时,手续费均向分单位进行取整(Math.floor),以规避微小的分账小数差错。
三、 用户下单与预约逻辑详解 (特有规则)
针对酒店类型商品(businessType = "hotel"),系统在下单和发券核销上设计了特殊的机制。
1. 团购模式下的下单与预约 (囤券预约制)
- 酒店团购商品:
- 下单与支付:用户调用
/groupbuy接口下单支付时,不需要提交入住人或预约日期等信息。 - 囤券发码:支付成功回调中,系统判定为酒店团购后,[XlOrderServiceImpl.java:L723](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L723) 规定不立即触发预约,仅为用户生成处于待预约状态(
status = 0)的券码(囤券)。 - 二次预约:用户后续在订单详情页手工点击预约,调用
POST /api/app/hotel/appointments接口提交预约日期和入住人信息,由XdHotelAppointmentServiceImpl#createFromVoucherRequest处理预约申请。
- 下单与支付:用户调用
- 其它普通团购商品:
- 支付成功后立即发券,生成可直接到店扫码使用的券码,不经过任何二次预约流程。
2. 拼团与套餐模式下的下单与预约 (下单即预约)
与团购“先囤券后预约”不同,拼团与套餐在遇到酒店商品时,采用下单时同步提交预约的模式:
- 拼团商品遇到酒店:
- 下单(开团
/createPintuanGroup或参团/joinPintuanGroup)时,[XlOrderServiceImpl.java:L1843](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L1843) 会强制校验预约参数:javaif ("hotel".equals(prod.getBusinessType())) { if (fi.getCheckInDate() == null || fi.getCheckInDate().isEmpty()) { throw new ServiceException("酒店商品请选择入离日期"); } } - 用户填写的入离日期(
checkInDate/checkOutDate)和入住人信息(guestName/guestPhone)会在下单阶段同步写入订单明细的快照字段snapshotJson中。
- 下单(开团
- 套餐商品遇到酒店:
- 用户调用
/package接口下单时,在参数中会同步包含套餐内酒店子项的入离日期及入住人信息。系统在保存子单时,直接将预约日期打包写入snapshotJson快照暂存。 - 支付成功后,[XlOrderServiceImpl.java:L710-L721](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L710-L721) 会检测当前子单是否为
"package"且含酒店商品。若满足,系统会自动调用预约服务创建预约申请,跳过用户在前端二次重复预约的动作,实现一步到位。
- 用户调用
四、 团购 / 拼团 业务流程
团购与拼团的底价模式业务流转如下:
1. 创建活动商品
- 商户在商家后台发布团购或拼团商品,选择
floor定价模式,填写settlementPrice(结算底价)。 - 校验规则:底价必填且不可为零或负数。
2. 平台定价与审核
- 平台管理员在平台管理后台对商户提交 of 活动进行审核,通过接口
setActivityPrice设置商品的最终前端售价activityPrice。 - 溢价计算:系统在此阶段自动计算平台加价(即溢价归平台): $$\text{platformMargin} = \text{activityPrice} - \text{settlementPrice}$$
3. 交易支付与资金冻结
- 用户在前台下单支付。
- 订单支付回调成功时,系统将子单的
settlementAmountFen(底价 $\times$ 数量)计算出来。 - 钱包服务
MerchantWalletServiceImpl.creditForOrder会生成一条业务类型为ORDER_FROZEN的记录,同时将底价收益冻结在商户钱包中。
五、 套餐 业务流程
套餐采用“商户提供子件底价,平台组装销售”的模式:
1. 商户发布底价套餐商品
- 商户在商户端发布商品,选择活动类型为
package,定价模式为floor,并设置其愿意接受的结算底价settlementPrice。该商品通过审核后,自动进入“套餐商品池”。
2. 平台组装套餐
- 平台管理员在平台后台创建套餐(
xl_package),设置对用户的套餐售价packagePrice。 - 从“套餐商品池”中挑选已入池的商品,添加到当前套餐下,生成
xl_package_item记录。
3. 套餐下单及拆单分摊机制
- 分摊算法(位于 [
XlOrderServiceImpl.java:splitPackageAmount](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L2827)): 如果为固定套餐(fixed),系统会收集该套餐内所有关联商品的底价settlementPrice,计算各自所占的比例,然后将用户支付的套餐总价(packagePrice)按比例分摊到每一个子商品的订单上,作为该子单的销售额;最后一单使用减法收余。 $$\text{子单分摊销售价} = \text{套餐总售价} \times \frac{\text{当前商品底价}}{\text{套餐内所有商品底价总和}}$$
六、 核心类与方法索引
开发人员在进行代码调整或维护时,可参考以下核心文件:
- 商户端商品提交与校验:
- 接口层:[
MerchantProductController.java](file:///d:/XieLi/Api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/merchant/MerchantProductController.java) - 校验核心:
validateDto(MerchantProductDto dto)(校验底价和售价是否填妥)
- 接口层:[
- 活动管理与默认比例配置:
- 服务层:[
XlProductActivityServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlProductActivityServiceImpl.java) - 核心方法:
insertActivity、updateActivity、setActivityPrice(设置最终售价并计算平台利润)
- 服务层:[
- 平台端套餐管理:
- 接口层:[
AdminPackageController.java](file:///d:/XieLi/Api/ruoyi-admin/src/main/java/com/ruoyi/web/controller/platform/AdminPackageController.java) - 核心服务:[
XlPackageServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlPackageServiceImpl.java)
- 接口层:[
- 套餐下单与拆单:
- 订单类型处理器:[
PackageOrderHandler.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/order/handler/PackageOrderHandler.java) - 分摊算法:[
XlOrderServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L2827-L2875) 的splitPackageAmount方法
- 订单类型处理器:[
- 酒店预约提交流程:
- 下单拦截与自动预约:[
XlOrderServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/XlOrderServiceImpl.java#L710) 的doPaySuccess方法 - 手动预约处理:
XdHotelAppointmentServiceImpl#createFromVoucherRequest
- 下单拦截与自动预约:[
- 钱包与财务结算:
- 钱包服务:[
MerchantWalletServiceImpl.java](file:///d:/XieLi/Api/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MerchantWalletServiceImpl.java) - 核心方法:
creditForOrder(支付成功冻结资金及收益)、unfreezeForOrder(核销完成底价解冻入账)
- 钱包服务:[