食堂采购系统源码数据库表结构与库存算法实现详解

简介: 本文详解食堂采购系统稳定性的核心:规范数据库结构(如goods、inventory、inventory_log三表协同)与强一致库存算法(乐观锁+流水驱动)。强调“库存是结果,流水是依据”,解决对账不准、超卖、负库存等顽疾,助你打造高并发、可商用的可靠系统。(239字)

很多食堂采购系统做不稳定,不是界面问题,而是底层数据结构和库存算法没设计好。
QQ20260119-152356.png

常见翻车现场你一定见过:

  • 库存经常对不上
  • 入库出库顺序混乱
  • 成本算不准
  • 多食堂同时扣库存直接变负数
  • 月底对账全靠人工补Excel

说白了:数据库结构不规范 + 库存算法太粗糙。

真正可商用的食堂采购系统源码,核心就两件事:

第一,表结构要可追溯
第二,库存算法要强一致

下面我用一套可直接落地的设计方案,把关键实现从表结构到代码完整拆开讲清楚。

一、核心业务流程梳理

先统一一个标准流程:

采购申请 → 采购单 → 入库 → 库存累加
领料/消耗 → 出库 → 库存扣减
盘点 → 差异调整
月底 → 成本核算 + 对账

所以数据库至少要支撑:

  • 供应商管理
  • 商品管理
  • 仓库管理
  • 采购入库
  • 出库领料
  • 实时库存
  • 库存流水

记住一句话:

库存 = 汇总结果
流水 = 真正依据

库存表只是“缓存”,库存流水才是“真相”。

二、核心数据库表结构设计

技术栈示例:

SpringBoot + MySQL + MyBatis

1 商品表 goods

CREATE TABLE goods (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  category_id BIGINT,
  unit VARCHAR(20),
  spec VARCHAR(100),
  enabled TINYINT DEFAULT 1,
  created_at DATETIME
);

作用:基础物料信息

示例:

  • 大米 50kg/袋
  • 鸡蛋 30枚/箱

2 供应商表 supplier

CREATE TABLE supplier (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(200),
  contact VARCHAR(50),
  phone VARCHAR(20),
  status TINYINT DEFAULT 1
);

3 仓库表 warehouse

CREATE TABLE warehouse (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  location VARCHAR(200)
);

支持:

  • 主仓
  • 冷藏仓
  • 分校区仓库

4 库存表 inventory(实时库存)

高频查询表

CREATE TABLE inventory (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  goods_id BIGINT,
  warehouse_id BIGINT,
  quantity DECIMAL(10,2) DEFAULT 0,
  amount DECIMAL(12,2) DEFAULT 0,
  version INT DEFAULT 0,
  UNIQUE KEY uk_goods_wh(goods_id, warehouse_id)
);

关键字段:

  • quantity 当前数量
  • amount 总成本
  • version 乐观锁

5 库存流水表 inventory_log(核心)

这是最重要的一张表

CREATE TABLE inventory_log (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  goods_id BIGINT,
  warehouse_id BIGINT,
  type VARCHAR(20),
  quantity DECIMAL(10,2),
  price DECIMAL(10,2),
  amount DECIMAL(12,2),
  ref_no VARCHAR(50),
  created_at DATETIME
);

type:

  • IN 入库
  • OUT 出库
  • ADJUST 盘点调整

所有库存变化必须写这张表。
QQ20250910-114722.png

三、库存算法设计思路

很多人直接:

update inventory set quantity = quantity - 10

这种做法必出事故。

正确思路:

库存变更三步走:

① 写库存流水
② 扣减库存(带锁)
③ 校验结果

四、入库算法实现(加库存)

Service 实现

@Transactional
public void stockIn(Long goodsId, Long warehouseId,
                    BigDecimal qty, BigDecimal price) {
   

    BigDecimal amount = qty.multiply(price);

    // 1 写流水
    inventoryLogMapper.insert(new InventoryLog(
            goodsId, warehouseId, "IN", qty, price, amount
    ));

    // 2 更新库存
    inventoryMapper.addStock(goodsId, warehouseId, qty, amount);
}

Mapper SQL

UPDATE inventory
SET quantity = quantity + #{
   qty},
    amount = amount + #{
   amount},
    version = version + 1
WHERE goods_id = #{
   goodsId}
AND warehouse_id = #{
   warehouseId};

五、出库算法实现(防止超卖)

重点来了。

出库一定要防:

  • 并发扣减
  • 库存负数

推荐方案:

乐观锁 + 条件扣减

核心SQL

UPDATE inventory
SET quantity = quantity - #{
   qty},
    amount = amount - #{
   amount},
    version = version + 1
WHERE goods_id = #{
   goodsId}
AND warehouse_id = #{
   warehouseId}
AND quantity >= #{
   qty}
AND version = #{
   version};

如果影响行数为 0 → 扣减失败。

Java实现

@Transactional
public void stockOut(Long goodsId, Long warehouseId,
                     BigDecimal qty) {
   

    Inventory inv = inventoryMapper.select(goodsId, warehouseId);

    if (inv.getQuantity().compareTo(qty) < 0) {
   
        throw new RuntimeException("库存不足");
    }

    BigDecimal avgPrice =
            inv.getAmount().divide(inv.getQuantity(), 2, RoundingMode.HALF_UP);

    BigDecimal amount = avgPrice.multiply(qty);

    int rows = inventoryMapper.reduceStock(
            goodsId, warehouseId, qty, amount, inv.getVersion());

    if (rows == 0) {
   
        throw new RuntimeException("库存并发冲突,请重试");
    }

    inventoryLogMapper.insert(
            new InventoryLog(goodsId, warehouseId, "OUT", qty, avgPrice, amount)
    );
}

六、成本算法(加权平均法)

食堂场景推荐:

加权平均法

原因:

  • 计算简单
  • 实时成本准确
  • 不用复杂批次管理

公式:

新平均价 = (旧金额 + 入库金额) ÷ (旧数量 + 入库数量)

SQL 示例:

amount / quantity

直接算即可。

七、高并发优化建议

如果是多校区或集团食堂,订单并发高时:

必须加:

1 分库分表(按仓库拆)
2 Redis库存缓存
3 批量入库写入
4 异步流水日志

否则库存表会成为瓶颈。
QQ20260119-152406.png

八、总结一句实战经验

如果你正在做食堂采购系统源码,记住这三条铁律:

库存只查 inventory
对账只查 inventory_log
任何库存变化必须走事务

这样系统跑几年都不会乱。

真正商用级系统,拼的不是功能多,而是:

数据稳定 + 算法可靠 + 并发安全

底层打牢,上层再怎么扩展都不怕。

相关文章
|
4月前
|
NoSQL 前端开发 数据挖掘
私域直播系统源码架构解析:从开播到成交的完整链路设计
本文深度解析私域直播系统源码级实现,涵盖推流鉴权、实时互动(WebSocket+Redis)、商品挂载、秒级下单、支付闭环及用户标签沉淀等全链路架构。强调技术可控、数据归属与业务可扩展性,助力企业构建稳定、自主、可复用的私域直播闭环。(239字)
|
3月前
|
消息中间件 算法 调度
外卖配送系统搭建方法核心:调度算法与任务分配机制实现思路
外卖配送系统的核心不在页面,而在调度算法。本文详解如何构建高效调度体系:从基础距离匹配、加权评分模型,到批量订单优化与微服务架构,涵盖数据模型、代码实现与生产实践,揭示智能调度才是决定履约效率与平台竞争力的关键壁垒。(239字)
|
3月前
|
消息中间件 NoSQL 算法
开源跑腿系统开发看似省钱,其实是技术债的开始?
创业者常问:“有开源跑腿系统吗?改改就能上线?”看似省钱,实则埋雷。多数开源项目缺并发控制、智能调度、分布式架构等核心能力,后期维护成本远超开发成本。真正关键不是“有没有代码”,而是你是否有技术掌控力——能否重构、修Bug、升级架构。开源是加速器,不是救命稻草。(239字)
|
3月前
|
消息中间件 算法 调度
外卖系统开发真的赚钱吗?90%的创业者可能选错了方向
外卖系统开发≠印钞机!90%创业者败在方向错误而非技术。本文直击本质:赚钱靠的是“商业模型+调度算法+生态构建”,而非简单CRUD。从高并发架构、智能派单到垂直场景切入,拆解真正可持续的盈利路径。(239字)
|
4月前
|
存储 人工智能 缓存
AI问诊系统开发架构解析:大模型 + 医疗知识库如何落地
本文详解可商用AI问诊系统落地实践:摒弃纯对话模式,采用“大模型+医疗知识库(RAG)+分诊规则引擎+业务系统”四层架构,解决幻觉、不可控、非结构化、合规风险等核心痛点,涵盖架构设计、知识检索、症状抽取、智能分诊与生产级部署关键代码与经验。(239字)
|
4月前
|
人工智能 缓存 知识图谱
互联网医院AI问诊系统架构设计:从智能分诊到在线诊疗的完整链路
本文详解互联网医院AI问诊系统落地实践:直击无效咨询多、分诊低效、医生负荷重等核心瓶颈,以微服务架构+AI独立部署为基座,覆盖智能分诊、结构化问诊、知识图谱+规则引擎、病历自动生成及高并发保障,实测降低医生工作量50%、提升分诊准确率至85%+。(239字)
|
1月前
|
存储 小程序 前端开发
私域直播带货小程序怎么搭建?一套完整流程讲清楚
本文详解私域直播带货小程序搭建全流程:涵盖需求分析、技术选型、前后端架构设计,及直播播放、商品管理、微信支付、分销裂变、消息推送等核心模块,并提供关键代码示例与高并发、库存同步等实战注意事项。(239字)
|
1月前
|
消息中间件 缓存 小程序
扫码点餐小程序搭建流程详解:从桌码到订单系统如何实现
本文详解扫码点餐小程序搭建全流程:涵盖桌码生成、动态菜单、购物车逻辑、订单与库存管理、微信支付接入、后厨打印及高并发优化(Redis缓存、消息队列、Nginx负载均衡),助力餐饮业降本增效、实现数字化升级。(239字)
|
2月前
|
存储 搜索推荐 数据安全/隐私保护
大健康私域直播系统搭建趋势:线上问诊与直播带动的模式升级
在大健康数字化加速背景下,单一问诊或电商模式难以为继。大健康私域直播系统通过“直播+问诊+服务+商品”融合,重构流量逻辑与技术架构,实现用户沉淀、信任建立与持续转化,打造闭环运营的业务操作系统。(239字)
|
8月前
|
Java
Java基础知识总结(超详细整理)
本文系统总结Java基础知识,涵盖语法、面向对象(类与对象、封装、继承、多态)、常用类(String、包装类、集合框架)及异常处理等核心内容,结合代码示例深入浅出,助你扎实掌握Java编程基础。
634 1

热门文章

最新文章