连锁门店库存+会员系统:一个人怎么管8家店

朋友开了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:餐饮菜谱成本是怎么算的?会随采购价变动吗?

系统维护标准菜谱(每种菜品需要多少食材),菜谱成本=各食材用量×最新采购价之和。每次采购入库后,系统自动用最新单价重算所有相关菜品的成本。这样菜谱成本始终反映最新的食材成本,毛利分析准确。

相关推荐
EIP低代码平台3 小时前
EIP低代码平台 - 应用管理 - 表单设计
低代码·c#·权限·工作流·netcore
Jeking2177 小时前
unione cloud 低代码平台 快速落地物料送检质检管理场景
低代码·流程引擎·表单设计·流程设计·表单引擎·unione cloud
雷工笔记1 天前
KingFusion系列34-KingFusion表格控件翻页问题分析与解决
笔记·低代码
梦梦代码精1 天前
PHP 还是 Java?LikeShop 多版本对比,附6条落地避坑建议
低代码·docker·开源·代码规范
汉得数字平台2 天前
飞搭系列 | 导入导出扩展能力:复杂业务逻辑灵活接入
低代码·ai coding·企业级paas平台
ebok.2 天前
低代码新潮流:京微智枢AI+低代码平台引领企业数智化变革
人工智能·低代码·rxjava
考勤技术解析2 天前
低代码搭建供应链管理系统的成本控制逻辑拆解
低代码·供应链管理系统·库存管理系统
快乐非自愿2 天前
2026低代码平台权威测评:多场景落地选型深度横评
人工智能·低代码·制造
EIP低代码平台2 天前
EIP低代码平台 - 系统日志
低代码·c#·权限·工作流·netcore