首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >食堂采购系统源码数据库表结构与库存算法实现详解

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

原创
作者头像
万岳教育Lili
发布2026-02-06 09:29:04
发布2026-02-06 09:29:04
1030
举报

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

食堂采购系统源码
食堂采购系统源码

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

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

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

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

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

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


一、核心业务流程梳理

先统一一个标准流程:

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

所以数据库至少要支撑:

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

记住一句话:

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

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


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

技术栈示例:

SpringBoot + MySQL + MyBatis


1 商品表 goods

代码语言:javascript
复制
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

代码语言:javascript
复制
CREATE TABLE supplier (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(200),
  contact VARCHAR(50),
  phone VARCHAR(20),
  status TINYINT DEFAULT 1
);

3 仓库表 warehouse

代码语言:javascript
复制
CREATE TABLE warehouse (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  location VARCHAR(200)
);

支持:

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

4 库存表 inventory(实时库存)

高频查询表

代码语言:javascript
复制
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(核心)

这是最重要的一张表

代码语言:javascript
复制
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 盘点调整

所有库存变化必须写这张表。


三、库存算法设计思路

很多人直接:

update inventory set quantity = quantity - 10

这种做法必出事故。

正确思路:

库存变更三步走:

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

食堂采购系统源码
食堂采购系统源码

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

Service 实现

代码语言:javascript
复制
@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

代码语言:javascript
复制
UPDATE inventory
SET quantity = quantity + #{qty},
    amount = amount + #{amount},
    version = version + 1
WHERE goods_id = #{goodsId}
AND warehouse_id = #{warehouseId};

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

重点来了。

出库一定要防:

  • 并发扣减
  • 库存负数

推荐方案:

乐观锁 + 条件扣减


核心SQL

代码语言:javascript
复制
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实现

代码语言:javascript
复制
@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 示例:

代码语言:javascript
复制
amount / quantity

直接算即可。


七、高并发优化建议

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

必须加:

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

否则库存表会成为瓶颈。

食堂采购系统源码
食堂采购系统源码

八、总结一句实战经验

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

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

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

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

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

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心业务流程梳理
  • 二、核心数据库表结构设计
    • 1 商品表 goods
    • 2 供应商表 supplier
    • 3 仓库表 warehouse
    • 4 库存表 inventory(实时库存)
    • 5 库存流水表 inventory_log(核心)
  • 三、库存算法设计思路
  • 四、入库算法实现(加库存)
    • Service 实现
    • Mapper SQL
  • 五、出库算法实现(防止超卖)
    • 核心SQL
    • Java实现
  • 六、成本算法(加权平均法)
  • 七、高并发优化建议
  • 八、总结一句实战经验
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档