朋友开了8家连锁便利店,每家店日均流水3000-5000元。听起来不错,但他快被库存和会员数据搞疯了。
每家店的库存各自为政------A店缺货了不知道B店有没有多的。会员卡只能在办卡的门店用,去其他店消费积分不同步。每月盘点8家店要跑一圈,花5天。
他找我帮忙。我用搭贝低代码平台花了2周搭了套多门店库存+会员管理系统。这篇文章记录核心设计。
一、多门店架构的核心问题
问题一:数据隔离
每家店只看到自己的库存和销售数据。但总部(朋友自己)能看到所有店的数据。
解决方案。 所有的数据表都加一个store_id字段。在搭贝平台中配置数据权限------门店员工只能看本店数据,总部角色能看全部。
python
class StoreInventory:
store_id: int # 门店ID
product_id: int # 商品
quantity: float # 库存数量
last_restocked: date # 最近补货日期
min_stock: float # 最低库存(低于此值预警)
class StoreTransaction:
store_id: int
type: str # sale / restock / transfer / adjustment
product_id: int
quantity: float
amount: float
operator: str
timestamp: datetime
问题二:门店间调拨
A店某商品缺货了,B店有富余。需要做门店调拨。
python
def create_transfer(from_store, to_store, items):
"""创建门店间调拨"""
transfer = db.insert('store_transfer', {
'from_store': from_store,
'to_store': to_store,
'items': items, # [{product_id, quantity}]
'status': 'pending',
'created_at': now()
})
# 锁定调出店的库存
for item in items:
inv = get_inventory(from_store, item['product_id'])
if inv['quantity'] - inv['locked_qty'] < item['quantity']:
return {'error': f'库存不足:{item["product_name"]}'}
db.update('store_inventory', inv['id'], {
'locked_qty': inv['locked_qty'] + item['quantity']
})
# 通知调出店发货
notify_store(from_store, f'调拨单{transfer["code"]}待发货')
return transfer
def confirm_transfer_received(transfer_id):
"""调入店确认收货"""
transfer = get_transfer(transfer_id)
for item in transfer['items']:
# 调出店扣减库存
from_inv = get_inventory(transfer['from_store'], item['product_id'])
db.update('store_inventory', from_inv['id'], {
'quantity': from_inv['quantity'] - item['quantity'],
'locked_qty': from_inv['locked_qty'] - item['quantity']
})
# 调入店增加库存
to_inv = get_or_create_inventory(
transfer['to_store'], item['product_id']
)
db.update('store_inventory', to_inv['id'], {
'quantity': to_inv['quantity'] + item['quantity']
})
# 记录调拨流水
db.insert('store_transaction', {
'store_id': transfer['from_store'],
'type': 'transfer_out',
'product_id': item['product_id'],
'quantity': -item['quantity']
})
db.insert('store_transaction', {
'store_id': transfer['to_store'],
'type': 'transfer_in',
'product_id': item['product_id'],
'quantity': item['quantity']
})
db.update('store_transfer', transfer_id, {'status': 'completed'})
问题三:会员跨店消费
会员在A店办的卡,到B店消费时积分要同步。
python
class Member:
member_id: int # 会员号(全局唯一)
name: str
phone: str
register_store: int # 注册门店
total_points: int # 总积分
total_spent: float # 累计消费
level: str # 普通/银卡/金卡/钻石
class MemberTransaction:
member_id: int
store_id: int # 消费门店
type: str # earn / redeem
points: int
amount: float
timestamp: datetime
def process_member_purchase(member_id, store_id, amount):
"""会员在门店消费,积分累计"""
member = get_member(member_id)
if not member:
return {'error': '会员不存在'}
# 计算积分(1元=1积分,金卡1.2倍,钻石1.5倍)
multipliers = {'普通': 1.0, '银卡': 1.0, '金卡': 1.2, '钻石': 1.5}
multiplier = multipliers.get(member['level'], 1.0)
points = int(amount * multiplier)
# 更新会员数据
db.update('member', member_id, {
'total_points': member['total_points'] + points,
'total_spent': member['total_spent'] + amount
})
# 检查是否升级
check_level_upgrade(member_id)
# 记录消费明细
db.insert('member_transaction', {
'member_id': member_id,
'store_id': store_id,
'type': 'earn',
'points': points,
'amount': amount,
'timestamp': now()
})
return {'points_earned': points, 'total_points': member['total_points'] + points}
def check_level_upgrade(member_id):
"""检查会员是否应该升级"""
member = get_member(member_id)
levels = [
('钻石', 50000), # 累计消费5万升级
('金卡', 20000),
('银卡', 5000),
('普通', 0)
]
for level, threshold in levels:
if member['total_spent'] >= threshold:
if member['level'] != level:
db.update('member', member_id, {'level': level})
notify_member(member, f'恭喜升级为{level}会员!')
break
二、智能补货
8家店的补货以前靠店长凭经验报。经常出现:A店积压了某商品、B店却断货了。
python
def smart_restock_suggestion():
"""智能补货建议"""
suggestions = []
products = get_all_products()
stores = get_all_stores()
for product in products:
# 统计各店库存
store_stocks = {}
for store in stores:
inv = get_inventory(store['id'], product['id'])
store_stocks[store['id']] = {
'quantity': inv['quantity'],
'min_stock': inv['min_stock'],
'daily_sales': get_avg_daily_sales(store['id'], product['id'], days=7)
}
# 找缺货的店
low_stores = [
(sid, s) for sid, s in store_stocks.items()
if s['quantity'] <= s['min_stock']
]
# 找富余的店
over_stores = [
(sid, s) for sid, s in store_stocks.items()
if s['quantity'] > s['daily_sales'] * 14 # 超14天销量
]
if low_stores and over_stores:
# 建议从富余店调拨到缺货店
for low_sid, low_data in low_stores:
need_qty = int(low_data['daily_sales'] * 7 - low_data['quantity'])
if need_qty <= 0:
continue
# 找最近的富余店
best_source = max(
over_stores,
key=lambda x: x[1]['quantity'] - x[1]['daily_sales'] * 7
)
available = int(
best_source[1]['quantity'] -
best_source[1]['daily_sales'] * 7
)
if available > 0:
transfer_qty = min(need_qty, available)
suggestions.append({
'product': product['name'],
'from_store': best_source[0],
'to_store': low_sid,
'qty': transfer_qty,
'reason': f'目标店库存{low_data["quantity"]},'
f'低于安全线{low_data["min_stock"]}'
})
return suggestions
朋友的使用反馈。 以前每周日晚上花3小时逐店看Excel库存表做补货决策。现在系统每周自动生成调拨建议,他花15分钟确认就行。
三、数据看板(给老板看的)
朋友最关心的是8家店的总盘子和每家店的单店数据。
python
def generate_daily_report():
"""每日营业报告"""
stores = get_all_stores()
report = {
'date': today(),
'total_revenue': 0,
'total_transactions': 0,
'total_member_spent': 0,
'stores': []
}
for store in stores:
transactions = get_today_transactions(store['id'])
revenue = sum(t['amount'] for t in transactions)
member_spent = sum(
t['amount'] for t in transactions
if t.get('member_id')
)
store_data = {
'name': store['name'],
'revenue': revenue,
'transactions': len(transactions),
'avg_ticket': revenue / len(transactions) if transactions else 0,
'member_ratio': member_spent / revenue * 100 if revenue else 0,
'low_stock_count': count_low_stock(store['id'])
}
report['stores'].append(store_data)
report['total_revenue'] += revenue
report['total_transactions'] += len(transactions)
report['total_member_spent'] += member_spent
# 排名
report['stores'].sort(key=lambda s: s['revenue'], reverse=True)
report['rankings'] = [
f'{i+1}.{s["name"]} ¥{s["revenue"]:.0f}'
for i, s in enumerate(report['stores'])
]
return report
每天早上7点自动推送到朋友企微。 包含8家店昨日营收排名、总营收、会员消费占比、低库存预警数量。
四、搭贝平台实现总结
12张核心表。 门店、商品、库存、会员、会员消费、销售流水、调拨单、补货建议等。
权限。 三级角色:总部(全部数据)、店长(本店数据)、店员(本店基础操作)。
移动端。 店员在企微中操作收银、会员查询、库存查询。不需要装额外APP。
搭建时间2周。朋友的8家店用了一个月就上手了。如果找软件公司定制多门店管理系统,报价20万+。
常见问题
Q1:连锁餐饮多店的库存数据能实时同步吗?
可以。各门店在系统中操作出入库时数据实时写入同一数据库。总部登录系统可以查看所有门店的实时库存。跨店调拨时,调出方发货后系统扣减其库存,调入方收货确认后增加其库存,全程数据联动。
Q2:餐饮菜谱成本是怎么算的?会随采购价变动吗?
系统维护标准菜谱(每种菜品需要多少食材),菜谱成本=各食材用量×最新采购价之和。每次采购入库后,系统自动用最新单价重算所有相关菜品的成本。这样菜谱成本始终反映最新的食材成本,毛利分析准确。