Skip to content

电商MVP #231

Description

@xiaoland

📑 Summary

为 MVP-HA 增加一系列有关于“电商”的最小限度的功能,服务 L1:re2 完成。

🤔 Rationale

电商是我们产品商业化的重要一环,在 L1:re2,包含下列商业化点:

  • 需要实现从广告、购买到履约的全过程:
    • 在合适的搭子请求中,推荐相关商品/服务;如接近饭点结束的搭子请求推荐餐厅套餐,拼车类型的搭子请求推荐网约车服务等等
  • 和“泰岛蛋”餐厅合作推出多人套餐,需要实现从广告到销售的全过程,是我们一项
    • 团购券由泰岛蛋门面核销(要设计一种尽可能避免给门店带来额外负担的核销方式)
    • 套餐允许由用户自由组合,最后整体打折(这样可以避免双人套餐不适合三人的搭子请求)
  • 自习搭子、羽毛球搭子所需的场地,我们需要提供“座位/场地预订”服务(这是一项服务,而不是免费的资源支持),并且预订存在成功与失败,成功还需要显示兑换信息(比如和服务员入座的口令、场地号等)
  • 网约车打车(聚合式)

而我们就需要最小程度地实现一套电商功能以支撑这些商业需求。

📏 Specification

梳理一下商业需求(卖什么,怎么卖),我觉得可以这样划分:

  • 权益凭证类( Entitlement ):用户购买的不是具体的物品或即时的服务,而是一个未来行使特权的契约。这种凭证本身可以流转、退款,直到被核销前,底层的真实服务/商品并未被消耗。如各类团购券(餐饮套餐券)、提货券、月卡会员、充值卡。
  • 时空资源类 (TimeSlotResource) :交易的本质是特定空间在特定时间段内的使用权,而非所有权。如羽毛球场预订、酒店客房预订、KTV 包厢、甚至指定时间的挂号看病。
  • 动态撮合服务类 (OnDemandFulfillment) :系统提供的是一个即时的供需匹配管道,服务提供方(供给)和消费者(需求)在地理位置和时间上高度随机。如网约车、外卖骑手调度、同城急修、代驾。

未来还可能有:

  • 离散资产类( TangibleGoods ):标的物是离散的、可计量的物理或虚拟实体。交易的本质是所有权的永久转移。如传统的实物电商(衣服、手机),以及直接发放的直充虚拟资产(如买Q币、买游戏道具、充值话费)。

顶层建模设计:

  • 产品 (Product) 或者说标的物 (Substance),进一步区分出 SPU, SKU (独立的模型,而不是 product type)
  • 广告 (Placement),一个容器,里面装的是 Offer
  • 售卖邀约 (Offer),负责产品捆绑和价格策略,也就是“怎么卖”
  • 订单 (Order),但这实际上是一个 Umbrella,根据产品类型走不同的订单领域,具体来说:
    • 离散资产类、权益资产类:GoodsOrder
    • 时空资源类:RentalOrder
    • 动态撮合服务类:还要进一步划分,目前仅分出 RideHailingOrder,否则会导致严重的“贫血模型(Anemic Domain Model)”和“数据库坏味道”
  • 履约 (Fulfillment),也是一个 Umbrella,根据产品类型走不同的履约领域
  • 账单 (Bill),为了支持 bill splitting,我们特别引入了该领域,而不是将 Bill 和 Payment 建模为一个领域;而且这下面还有 Bill Share ,其和 Payment 的关系是 【 1 x Bill -> N x Bill Share -> M x PaymentTx】
  • 支付 (Payment),只关心单笔资金流,负责与外部第三方支付网关(微信、支付宝、Stripe)交互,记录资金流转

产品的建模是统一的,不论是网约车、场地设施租赁还是团购券,都可以用 SKU/SPU 建模覆盖:

  • 网约车业务的 SPU/SKU 映射:
    • 商品类目 (Category):出行服务
    • SPU(服务抽象):专车 (Comfort Car)
    • SKU(具体计费/服务单元):由于动态服务受地域和时段影响极大,SKU 通常是“车型 + 城市 + 时段”的组合。
      • SKU 1:专车 - 北京市 - 平峰期(关联特定的起步价、里程费率、时长费率)
      • SKU 2:专车 - 北京市 - 夜间(关联更高的夜间费率)
    • 当用户呼叫专车时,系统实际上是在“购买”对应的 SKU。这个 SKU ID 会被传递给下游的 RideOrder,作为行程结束后计算最终账单的规则快照。通过复用商品模型,可以利用现成的商品中心完成各类服务的上下架、定价和营销(如:专车通用 8 折券)。

TODO 还有很多设计细节需要讨论

待整理:

  • 目前仅 PR Page 的 Utility Area 下面有 Placement 的位置(1-col n-rows),而且 Placement 是按 PR Context 选择性显示的(比如临近饭点结束的 PR,则为某餐厅的团购套餐 Offer;如烹饪搭子,则是DIY厨房场地预订的 Offer 等)
  • 网约车服务也有 Offer,但不像传统的 Offer 是所见即所得价格直接写到订单中,而是【询价与预估】+【缔约与快照】(将优惠计算逻辑写入到订单中)+【履约收集】+【清算与账单生成】,这也进一步体现单独拆分 RideHailing Order 的必要性
  • 在 PR 内,点击 Placement 会跳转到 Offer Detail (如果该 Offer 在该 PR 内没有订单) / Order Detail (如果有订单)
  • 场地预订会需要收集额外的信息,比如联系方式(手机号)、实名信息(法定姓名、居民身份证号码),这些应当是订单的属性
  • 订单默认超时时间为 30 分钟
  • 产品(SKU/SPU)详情包括参数、长图、头图
  • 在 PR 内创建的订单是属于多个人(active participants)的,需要多人分摊费用、选择与配置自己的产品,这和传统电商平台的下单是 Synchronous Scalar Action 不同,是一个 Asynchronous Coordination Problem,为此我们得引入一个独立的对象承载【收集意向、达成共识、冻结规则】,并且能支撑【6选3咖啡33元Offer,而每个人需要独立选择自己的咖啡配置】具体来说我会设计
[ TradeProposal (多方交易提议) ]
  ├── Proposal_ID: "P_1001"
  ├── Target_Offer: "Offer_6选3咖啡套餐_33元"
  ├── Split_Rule: "AA均摊" (每人需支付 11 元)
  │
  ├── Item_Slots (履约明细槽位 - 本次新增)
  │    ├── Slot_1: { Status: 'FILLED',  Owner: 'User_A', Selected_SKU: '拿铁(热/无糖)' }
  │    ├── Slot_2: { Status: 'FILLED',  Owner: 'User_B', Selected_SKU: '美式(冰/标冰)' }
  │    └── Slot_3: { Status: 'PENDING', Owner: 'User_C', Selected_SKU: null }
  │
  └── Participants (参与者与财务份额)
       ├── User_A: { Status: 'Accepted', Share_Amount: 11 }
       ├── User_B: { Status: 'Accepted', Share_Amount: 11 }
       └── User_C: { Status: 'Pending',  Share_Amount: 11 }
  • Entitlement 的一种形式就是 Voucher
  • After sales

Acceptance Criteria

TODO

🚧 Technical Constraints

已经完成 #229

⏪ Backward Compatibility

🔄 Alternatives Considered

📚 References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions