连锁门店库存+会员系统:一个人怎么管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:餐饮菜谱成本是怎么算的?会随采购价变动吗?

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

相关推荐
杰夫(简道云个人搭建)19 小时前
SAAS系统应该先解决业务问题,再优化体验
数据库·人工智能·低代码·excel·个人开发
Devlab1 天前
LVGL设计大师——网页版anyui来了!!
嵌入式硬件·物联网·低代码·ui·iot
jonyleek2 天前
JVS-Logic 实践指南:基于私有化与柔性配置的企业级逻辑引擎落地方法
人工智能·低代码·私有化部署·企业集成·逻辑引擎·流程编排·jvs
皮皮虾❀2 天前
典铭云赛低代码+AI智能体快速落地方法论:从“售前写方案、交付做开发各管一段”到“场景发现即交付、需求到上线一周”的完整技术方案
人工智能·低代码
jonyleek3 天前
JVS-Rules 实践指南:三步实现风控与营销规则的自主配置(附可操作闭环)
低代码·系统集成·决策系统·风控系统·合规审计·jvs-rules·jvs规则引擎
HUIBUR科技3 天前
先治数据,再做报表:企业数字化时代的数据治理前置逻辑与轻量化落地路径
低代码
技术分享官3 天前
Geejing WebBuilder|主副表(主子表)联动标准配置
低代码
许彰午4 天前
政务低代码平台实战⑤:双输出模式——存DB与导出JSP的完整链路
数据库·低代码·政务
梦梦代码精4 天前
连锁品牌数字化:从门店扩张到用户资产运营的技术底座
大数据·人工智能·低代码·docker·开源·代码规范
SL-staff4 天前
JVS数字底座实践:如何复用企业文档能力快速构建知识类应用
低代码·微服务·springcloud·知识管理·权限控制·jvs·elasticsea