分仓(多仓库):从「全球一盘货」到「就近发货」

AI摘要
本文介绍了电商系统分仓(多仓库)的产品设计与技术实现,属于知识分享。内容从产品逻辑(用户选仓、商品按仓展示、购物车与结账隔离、运费计算、订单记录)和技术实现(数据模型、会话管理、商品作用域过滤、运费计算器扩展)两方面,系统阐述了如何将“一个店铺、多个发货地”的能力集成到系统中,以优化跨境或跨区域销售的物流时效与成本,并为库存分仓等高级功能提供了扩展基础。

分仓(多仓库):从「全球一盘货」到「就近发货」

项目:gitee.com/teanary/teanary_service

为什么需要分仓?

当你的茶叶卖到欧洲、北美和国内,如果全部从云南仓发货,海外用户要等半个月,运费也高。如果能在当地设仓,从本地发货,时效和成本都会好很多。分仓就是把「一个店铺、多个发货地」做进系统:用户选仓、商品按仓展示、邮费从仓算起、订单带上发货仓,前后端一气呵成。

本文简要介绍 Teanary 里的分仓设计:产品逻辑、技术实现和你可以怎么用。


产品侧:用户看到什么

  • 右上角选仓

和语言、货币并列,多了一个「分仓」下拉。用户选「默认仓库」「欧洲仓」「美国仓」等,当前会话就固定在这个仓,列表、购物车、结账都只针对该仓。

  • 商品按仓可见

商品和仓库是多对多关联(一个商品可挂多个仓)。前台只展示当前所选仓库下的商品;首页精选、分类列表、搜索、推荐、随机商品都只出当前仓,避免用户加了一车「欧洲仓」商品却从「国内仓」结账的混乱。

  • 购物车与结账

购物车展示时只显示当前仓的商品;去结账时再次校验,只允许当前仓商品进入结算。切换仓库会清空购物车,避免跨仓混单。

  • 邮费从仓算

运费计算的起点是当前选中仓库的发货地(国家/省/城市等),终点是用户填的收货地址。后续若要按「国内/国际」「同城免邮」等做差异化,都可以基于「发货仓 + 收货地址」扩展。

  • 订单带上发货仓

下单时把当前 warehouse_id 写入订单;个人中心订单列表、订单详情里会显示「发货仓库」,方便用户和运营核对。


技术侧:怎么实现的

  • 数据模型

  • warehouses:仓库主表(名称、编码、国家/省/市/地址、电话、是否默认、排序等)。

  • product_warehouse:商品与仓库多对多;一个商品可挂在多个仓。

  • orders.warehouse_id:订单所属发货仓,可为空以兼容老单。

  • 当前仓的传递

和语言、货币类似:中间件在请求里解析/设置 session('warehouse_id'),默认仓由 WarehouseService::getDefaultWarehouse() 决定;切换仓的接口更新 session,并清空 cart_id 避免跨仓购物车。

  • 商品作用域

Product::scopeForWarehouse($query, $warehouseId):当 $warehouseId 非空时,whereHas('warehouses', ...) 只保留在该仓下的商品。列表、精选、推荐、随机、搜索、购物车过滤、结账校验都统一用「当前 session 仓 + 该 scope 或等价过滤」。

  • 邮费计算

运费计算器接口增加可选参数「发货仓」;ShippingService 从 session 取当前仓,把仓库对象传给计算器。计算器内部仍按「目的国/区域 + 重量等」算费,起点信息可用于后续做同城/国内/国际区分。

  • 缓存与后台

仓库列表由 WarehouseService 提供,带缓存;后台有仓库 CRUD、商品表单里多选「可发货仓库」。商品保存时 warehouses()->sync($warehouseIds),保证前台按仓过滤时数据一致。


小结

分仓把「多发货地」做成一级能力:选仓 → 看当前仓商品 → 购物车/结账仅当前仓 → 邮费从该仓算 → 订单记录发货仓,逻辑清晰、前后端统一。若你后面要做「库存分仓」「就近推荐仓库」或更复杂的运费策略,当前这套仓库与订单、商品的关联也可以直接作为基础扩展。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!