# 物料管理系统数据库表说明 更新时间:2026-10-08。数据库:当前本地 MySQL `wmms`,共 **30 张表**。 本文按照“表、保存什么、主要字段”介绍每张表的作用,后面单独列出表之间的关系。依据当前数据库结构、`scripts/init.sql` 和后端读写代码核对。 通用字段:`id` 为记录主键;`organization_id` 为本方经营组织 ID;`created_at`、`updated_at` 分别为创建、更新时间。表已创建与对应业务功能已完整实现是两件事,未接入当前业务流程的结构在第 9 节说明。 ## 1. 本方组织、用户与权限 | 表 | 保存什么 | 主要字段 | |---|---|---| | `organizations` | 本方公司或核算主体,例如北京公司、武汉公司;用于确定业务数据归属。 | 组织ID(`id`)、组织编码(`code`)、组织名称(`name`)、状态(`status`)、默认时区(`default_timezone`)、`created_at`、`updated_at` | | `users` | 系统登录账号和用户说明。 | 用户ID(`id`)、用户名(`username`)、密码哈希(`password`)、用户说明(`description`)、`created_at` | | `roles` | 超级管理员、仓库管理员、采购、技术、生产、销售等角色定义。 | 角色ID(`id`)、角色编码(`code`)、角色名称(`name`)、是否启用(`enabled`)、`created_at`、`updated_at` | | `permissions` | 查看物料、维护供应商、维护出入库等可授权的操作能力。 | 权限ID(`id`)、权限编码(`code`)、权限名称(`name`)、`created_at` | | `user_roles` | 用户拥有哪些角色。 | 用户ID(`user_id`)、角色ID(`role_id`)、分配时间(`created_at`) | | `role_permissions` | 角色拥有哪些权限。 | 角色ID(`role_id`)、权限ID(`permission_id`)、授权时间(`created_at`) | | `user_organizations` | 用户可访问的组织范围及默认组织。 | 用户ID(`user_id`)、组织ID(`organization_id`)、默认组织标记(`is_default`)、`created_at` | | `user_warehouses` | 用户可访问的仓库范围。 | 用户ID(`user_id`)、仓库ID(`warehouse_id`)、`created_at` | | `revoked_tokens` | 被撤销令牌的登记结构,供令牌失效机制使用。 | 令牌标识(`jti`,主键)、用户ID(`user_id`)、原到期时间(`expires_at`)、撤销时间(`revoked_at`) | ## 2. 物料与基础字典 | 表 | 保存什么 | 主要字段 | |---|---|---| | `materials` | 物料基础资料,用于识别和描述物料;库存余额另存。 | 物料ID(`id`)、所属组织(`organization_id`)、物料编码(`material_code`)、名称(`name`)、图片(`material_image`)、规格(`spec`)、厂商型号(`manufacturer_model`)、分类ID(`category_id`)、基本单位ID(`base_unit_id`)、单位文本(`unit`)、状态(`status`)、资料版本(`version`)、`created_at`、`updated_at` | | `material_categories` | 物料大类、子类及分类定义,形成分类树。 | 分类ID(`id`)、所属组织(`organization_id`)、编码(`code`)、名称(`name`)、分类说明(`description`)、父分类ID(`parent_id`)、状态(`status`) | | `units` | 个、瓶、包、升等计量单位字典及数量精度。 | 单位ID(`id`)、所属组织(`organization_id`)、单位编码(`code`)、单位名称(`name`)、小数位数(`precision_scale`)、状态(`status`) | | `code_rules` | 按组织和物料分类配置的编码生成规则。 | 规则ID(`id`)、所属组织(`organization_id`)、分类ID(`category_id`)、编码前缀(`prefix`)、流水号长度(`sequence_length`)、下一个流水号(`next_sequence`)、状态(`status`) | | `material_unit_conversions` | 特定物料在两个计量单位之间的换算系数及有效期。 | 规则ID(`id`)、所属组织(`organization_id`)、物料ID(`material_id`)、来源单位ID(`from_unit_id`)、目标单位ID(`to_unit_id`)、换算系数(`conversion_rate`)、生效日期(`effective_from`)、失效日期(`effective_to`) | | `tags` | 物料关联的唯一码或标签,用于按标签查找物料。 | 标签ID(`id`)、物料ID(`material_id`)、标签编码(`tag_code`)、`created_at` | ## 3. 客户、供应商与供货关系 | 表 | 保存什么 | 主要字段 | |---|---|---| | `business_partners` | 企业基本资料,多个本方组织可以共用。 | 企业ID(`id`)、企业名称(`legal_name`)、统一社会信用代码(`unified_credit_code`)、联系人(`contact_name`)、电话(`contact_phone`)、地址(`address`)、`created_at`、`updated_at` | | `organization_partners` | 当前组织如何与这家企业合作。 | 关系ID(`id`)、所属组织(`organization_id`)、企业ID(`business_partner_id`)、伙伴编码(`partner_code`)、供应商身份(`is_supplier`)、客户身份(`is_customer`)、供应商状态(`supplier_status`)、客户状态(`customer_status`)、供应商分类(`supplier_categories`)、客户分类(`customer_categories`)、结算币种(`settlement_currency`)、付款条款(`payment_terms`)、`created_at`、`updated_at` | | `material_suppliers` | 某个物料由哪个供应商供货,以及报价和供货条件。 | 记录ID(`id`)、所属组织(`organization_id`)、物料ID(`material_id`)、组织伙伴关系ID(`organization_partner_id`)、价格(`price`)、币种(`currency`)、最小订购量(`minimum_order_quantity`)、供货周期天数(`lead_time_days`)、首选标记(`is_preferred`)、生效日期(`effective_from`)、失效日期(`effective_to`)、状态(`status`) | 同一外部企业可以与北京、武汉分别建立合作关系。企业名称、联系人、地址等基础资料共用;客户/供应商身份、状态和分类按组织分别保存。同一关系可同时具有客户和供应商身份。 `supplier_categories` 与 `customer_categories` 均支持多选:`material` 表示“物料级(生产)”,`finished_product` 表示“成品级(经营买卖)”;空集合表示未分类。 ## 4. 仓库、库位与库存 | 表 | 保存什么 | 主要字段 | |---|---|---| | `warehouses` | 本方组织的仓库资料。 | 仓库ID(`id`)、所属组织(`organization_id`)、仓库编码(`code`)、名称(`name`)、状态(`status`)、`created_at`、`updated_at` | | `warehouse_locations` | 某个仓库内部的存放位置。 | 库位ID(`id`)、所属仓库(`warehouse_id`)、库位编码(`code`)、名称(`name`)、状态(`status`)、`created_at`、`updated_at` | | `inventory_balances` | 某物料在某组织、仓库、库位的当前库存余额。 | 余额ID(`id`)、组织ID(`organization_id`)、仓库ID(`warehouse_id`)、库位ID(`location_id`)、物料ID(`material_id`)、现存量(`on_hand`)、预留量(`reserved`)、锁定量(`locked`)、在途量(`in_transit`)、库存版本(`version`)、`updated_at` | | `stock_warning_rules` | 某组织、仓库、物料的库存预警规则。 | 规则ID(`id`)、组织ID(`organization_id`)、仓库ID(`warehouse_id`)、物料ID(`material_id`)、预警阈值(`minimum_available`)、是否启用(`enabled`)、`created_at`、`updated_at` | 库位通过所属仓库确定组织。库存余额按库位保存,预警规则按仓库保存。当前预警查询使用现存量口径,启用且现存量小于等于阈值时预警,阈值为 0 也有效。 ## 5. 入库与出库单据 | 表 | 保存什么 | 主要字段 | |---|---|---| | `inbound_orders` | 一次入库操作的公共信息,即入库单表头。 | 单据ID(`id`)、所属组织(`organization_id`)、仓库ID(`warehouse_id`)、库位ID(`location_id`)、入库单号(`inbound_no`)、操作人(`operator`)、入库时间(`inbound_date`)、经手人(`handler`)、供应商文本(`supplier`)、备注(`remark`)、`created_at`、`updated_at` | | `inbound_items` | 入库单中逐项入库的物料和数量。 | 明细ID(`id`)、入库单ID(`inbound_order_id`)、物料ID(`material_id`)、数量(`quantity`)、`created_at` | | `outbound_orders` | 一次出库操作的公共信息,即出库单表头。 | 单据ID(`id`)、所属组织(`organization_id`)、仓库ID(`warehouse_id`)、库位ID(`location_id`)、出库单号(`outbound_no`)、操作人(`operator`)、出库时间(`outbound_date`)、经手人(`handler`)、接收方文本(`receiver`)、备注(`remark`)、旧库状态字段(`status`)、`created_at`、`updated_at` | | `outbound_items` | 出库单中逐项出库的物料和数量。 | 明细ID(`id`)、出库单ID(`outbound_order_id`)、物料ID(`material_id`)、数量(`quantity`)、`created_at` | 一张单据可以有多条物料明细;当前仓库、库位保存在表头,明细没有独立库位。`supplier`、`receiver`、`operator`、`handler` 均为文本,不是伙伴或用户表外键。 ## 6. 物料申请与审批 | 表 | 保存什么 | 主要字段 | |---|---|---| | `material_applications` | 一次物料领用申请的申请人、用途和审批结果。 | 申请ID(`id`)、申请人ID(`user_id`)、用途(`purpose`)、申请状态(`status`)、驳回原因(`rejection_reason`)、审批人ID(`approved_by`)、`created_at`、`updated_at` | | `application_items` | 申请中需要领用的物料和数量。 | 明细ID(`id`)、申请ID(`application_id`)、物料ID(`material_id`)、申请数量(`quantity`) | 申请状态为 `pending`(待审批)、`approved`(已通过)、`rejected`(已驳回)、`cancelled`(已取消)。当前申请明细引用已有物料;新增物料生成编码属于另一条主数据流程。 审批选择自动出库时,当前代码生成出库单和明细、扣减库存并记录流水;仅审批模式只更新审批状态。申请表没有直接指向生成出库单的字段,也没有 `organization_id` 或个人库存字段。 ## 7. 物料变更日志与库存流水 | 表 | 保存什么 | 主要字段 | |---|---|---| | `material_logs` | 物料资料新增、修改等操作及修改前后快照。 | 日志ID(`id`)、操作类型(`operation_type`)、物料ID(`material_id`)、旧值快照(`old_value`)、新值快照(`new_value`)、操作人(`operator`)、说明(`description`)、`created_at` | | `stock_logs` | 库存增减数量、方向和来源单据。 | 流水ID(`id`)、物料ID(`material_id`)、方向(`type`)、数量(`quantity`)、来源类型(`related_order_type`)、来源记录ID(`related_order_id`)、`created_at` | `material_logs` 描述资料变化,`stock_logs` 描述数量变化。库存流水的 `type` 为 `in` 或 `out`;来源类型包含 `inbound`、`outbound`、`application`,分别指向入库单、出库单、申请主键。 ## 8. 表之间的关系 ### 8.1 关系如何理解 | 关系 | 保存方式 | 例子 | |---|---|---| | 一对多 | 多的一方保存主表ID。 | 一个入库单对应多个入库明细:`inbound_items.inbound_order_id → inbound_orders.id`。 | | 多对多 | 中间表同时保存两边的ID。 | 用户与角色通过 `user_roles` 关联;组织与企业通过 `organization_partners` 关联。 | | 自关联 | 记录引用同一张表的另一条记录。 | `material_categories.parent_id → material_categories.id`,表示分类父子关系。 | | 逻辑关联 | 代码按字段查询,数据库未设置外键。 | 申请人ID关联用户、库存流水按来源类型及ID关联单据。 | ### 8.2 当前实际存在的外键 以下按数据库元数据逐项列出。外键确保引用记录存在;记录是否同属一个组织,还需要业务层校验。 | 子表字段 | 引用主表字段 | |---|---| | `application_items.application_id` | `material_applications.id` | | `application_items.material_id` | `materials.id` | | `code_rules.category_id` | `material_categories.id` | | `code_rules.organization_id` | `organizations.id` | | `inbound_items.material_id` | `materials.id` | | `inbound_items.inbound_order_id` | `inbound_orders.id` | | `inbound_orders.location_id` | `warehouse_locations.id` | | `inbound_orders.organization_id` | `organizations.id` | | `inbound_orders.warehouse_id` | `warehouses.id` | | `inventory_balances.location_id` | `warehouse_locations.id` | | `inventory_balances.material_id` | `materials.id` | | `inventory_balances.organization_id` | `organizations.id` | | `inventory_balances.warehouse_id` | `warehouses.id` | | `material_categories.organization_id` | `organizations.id` | | `material_categories.parent_id` | `material_categories.id` | | `material_suppliers.material_id` | `materials.id` | | `material_suppliers.organization_id` | `organizations.id` | | `material_suppliers.organization_partner_id` | `organization_partners.id` | | `material_unit_conversions.from_unit_id` | `units.id` | | `material_unit_conversions.material_id` | `materials.id` | | `material_unit_conversions.organization_id` | `organizations.id` | | `material_unit_conversions.to_unit_id` | `units.id` | | `materials.base_unit_id` | `units.id` | | `materials.category_id` | `material_categories.id` | | `materials.organization_id` | `organizations.id` | | `organization_partners.organization_id` | `organizations.id` | | `organization_partners.business_partner_id` | `business_partners.id` | | `outbound_items.material_id` | `materials.id` | | `outbound_items.outbound_order_id` | `outbound_orders.id` | | `outbound_orders.location_id` | `warehouse_locations.id` | | `outbound_orders.organization_id` | `organizations.id` | | `outbound_orders.warehouse_id` | `warehouses.id` | | `revoked_tokens.user_id` | `users.id` | | `role_permissions.permission_id` | `permissions.id` | | `role_permissions.role_id` | `roles.id` | | `stock_logs.material_id` | `materials.id` | | `stock_warning_rules.material_id` | `materials.id` | | `stock_warning_rules.organization_id` | `organizations.id` | | `stock_warning_rules.warehouse_id` | `warehouses.id` | | `tags.material_id` | `materials.id` | | `units.organization_id` | `organizations.id` | | `user_organizations.organization_id` | `organizations.id` | | `user_organizations.user_id` | `users.id` | | `user_roles.role_id` | `roles.id` | | `user_roles.user_id` | `users.id` | | `user_warehouses.user_id` | `users.id` | | `user_warehouses.warehouse_id` | `warehouses.id` | | `warehouse_locations.warehouse_id` | `warehouses.id` | | `warehouses.organization_id` | `organizations.id` | ### 8.3 逻辑关联及间接关联 | 表之间的关系 | 关联字段 | 说明 | |---|---|---| | 申请 → 申请人 | `material_applications.user_id → users.id` | 当前实际库未设置用户外键,代码查询申请人资料。 | | 申请 → 审批人 | `material_applications.approved_by → users.id` | 当前无外键;未审批时通常为 0。 | | 物料日志 → 物料 | `material_logs.material_id → materials.id` | 当前实际库无外键。 | | 库存流水 → 入库单 | `related_order_type = inbound` 时,`related_order_id → inbound_orders.id` | 按类型和ID配对查询。 | | 库存流水 → 出库单 | `related_order_type = outbound` 时,`related_order_id → outbound_orders.id` | 按类型和ID配对查询。 | | 库存流水 → 申请 | `related_order_type = application` 时,`related_order_id → material_applications.id` | 自动出库流水保存的是申请ID,不是生成的出库单ID。 | | 库位 → 组织 | `warehouse_locations.warehouse_id → warehouses.organization_id` | 通过仓库间接确定组织。 | | 物料 → 编码规则 | 组织及分类对应 `code_rules` | 物料只保存生成的编码文本,没有编码规则ID字段。 | | 申请 → 自动生成的出库单 | 当前没有直接关联字段 | 属于业务生成过程,不能按现有表头字段直接定位关联单据。 | ### 8.4 主要唯一约束 | 表 | 唯一字段或组合 | 含义 | |---|---|---| | `organizations`、`roles`、`permissions` | `code` | 各自表内编码唯一。 | | `users` | `username` | 用户名唯一。 | | `business_partners` | `unified_credit_code` | 已填写的信用代码唯一,允许为空;企业名称没有唯一约束。 | | `organization_partners` | `(organization_id, business_partner_id)`;`(organization_id, partner_code)` | 同一组织与同一企业只有一条合作关系;伙伴编码在组织内唯一。 | | `materials` | `(organization_id, material_code)` | 物料编码在组织内唯一。 | | `material_categories`、`units`、`warehouses` | `(organization_id, code)` | 分类、单位、仓库编码分别在组织内唯一。 | | `warehouse_locations` | `(warehouse_id, code)` | 库位编码在仓库内唯一。 | | `code_rules` | `(organization_id, category_id)` | 同一组织同一分类只有一条编码规则。 | | `inventory_balances` | `(organization_id, warehouse_id, location_id, material_id)` | 同一库存维度只有一条余额。 | | `stock_warning_rules` | `(organization_id, warehouse_id, material_id)` | 同一仓库同一物料只有一条预警规则。 | | `tags` | `tag_code` | 标签编码全表唯一。 | | `inbound_orders`、`outbound_orders` | `inbound_no`、`outbound_no` | 各自单据表内单号唯一。 | | `user_roles` | `(user_id, role_id)` 联合主键 | 同一用户不会重复分配同一角色。 | | `role_permissions` | `(role_id, permission_id)` 联合主键 | 同一角色不会重复分配同一权限。 | | `user_organizations` | `(user_id, organization_id)` 联合主键 | 同一组织授权不会重复。 | | `user_warehouses` | `(user_id, warehouse_id)` 联合主键 | 同一仓库授权不会重复。 | ## 9. 当前结构与使用范围 | 项目 | 当前情况 | |---|---| | 令牌撤销 | `revoked_tokens` 结构已建,当前认证代码未查询该表;退出登录主要由客户端清除令牌。 | | 物料单位换算 | `material_unit_conversions` 结构已建,当前后端未见该表业务读写路径;库存余额支持小数,但出入库、申请明细及流水数量仍为 INT。 | | 物料供应商条件 | `material_suppliers` 结构已建,用于供货、报价等需求;当前后端未见完整维护路径。 | | 实物追踪 | `tags` 只有物料和标签关系,没有库位、单据明细或实物流转状态;物料表没有序列号开关。 | | 组织范围 | 多数业务表有组织字段;当前申请表、库存流水和物料日志没有直接组织字段。角色分配也没有按组织分别保存。 | | 伙伴资料共享 | 多个组织引用同一企业ID时,修改企业名称、联系人等基础资料会影响共享记录;合作身份、分类、状态分别保存。当前新建接口仍直接新增企业记录。 | | 库存口径 | 结构支持现存、预留、锁定、在途数量;当前主要出入库代码修改默认组织、默认仓库、主库位的现存量。 | | 可用库存 | 设计口径为 `on_hand - reserved - locked`;当前预警查询使用现存量,不能仅根据阈值字段名推断已使用可用量。 | | 日志口径 | 物料日志实际库快照为JSON、操作类型为ENUM;库存流水编辑单据时可能重建,不是不可修改的完整审计日志。 | | 出库状态 | 当前库保留 `outbound_orders.status`,但现有代码未按此列维护状态;初始化脚本没有该列。 | | 物料类型 | 初始化脚本另有 `material_types` 和 `materials.material_type_id`;当前实际库及当前物料模型没有这两项。该表未计入本文的30张现有表。 | | 申请单号 | 页面字段 `application_no` 由申请主键派生,申请表没有该列。 | | 后续模块 | 当前库没有BOM专用表、盘点单专用表、周期提醒专用表或申请人个人库存表。 | ## 10. 数据库初始化 | 文件 | 用途 | |---|---| | `scripts/init.sql` | 空库首次初始化,包含表结构、客户和供应商分类字段、物料分类及编码规则,以及明确标注的20家虚构企业示例数据。 | 初始化脚本直接建立分类说明字段、6 个大类和 28 个子类、父子分类关系,以及“子类编码 + 4 位流水号”的编码规则。出入库表直接包含单据编号、操作人和备注字段。 库存预警阈值为 0 是有效配置,表示库存降到 0 时预警;新库没有需要清理的历史预警规则。 已有数据库需要保留数据时,应先备份,再根据实际结构差异准备并验证增量 SQL;不要直接重复执行完整初始化脚本。