# 库存校验功能集成总结 ## 实施日期 2026-02-24 ## 功能概述 在 `RunBOMExtraction` 过程中集成了库存校验功能,针对部件物料进行库存检查。根据订单顺序累加需求量,当库存充足时使用部件,不足时使用子件(接头+弹性元件)。 ## 修改的文件 ### 1. M04_Config.bas **修改内容:** 添加现存量工作表配置常量 ```vba ' 现存量工作表配置常量 Public Const INVENTORY_SHEET_NAME As String = "现存量" Public Const INVENTORY_HEADER_ROW As Long = 3 ' 表头在第3行 Public Const INVENTORY_COL_CODE As String = "B" ' B列 = 物料编码 Public Const INVENTORY_COL_QTY As String = "J" ' J列 = 库存数量 ``` ### 2. M08_ComponentProcessor.bas **修改内容:** #### 2.1 添加库存追踪模块级变量 ```vba ' 模块级变量 - 库存追踪 Private g_InventoryDict As Object ' 部件编码 -> 现存量 Private g_AccumulatedDemandDict As Object ' 部件编码 -> 累计需求量 ``` #### 2.2 新增 `LoadInventoryData` 函数 - 从[现存量]工作表加载库存数据 - 表头在第3行,从第4行开始读取 - B列 = 物料编码,J列 = 库存数量 - 如果未找到工作表,记录警告并使用空字典(所有库存视为0) #### 2.3 新增 `InitComponentProcessorWithInventory` 函数 - 初始化部件处理器,同时加载库存数据 - 创建累计需求量字典 - 调用 `LoadInventoryData` 加载库存 #### 2.4 重写 `CheckComponentInventory` 函数 **输入参数:** - `wsComponent` - "部件"工作表 - `rowNum` - 匹配到的行号 - `headerMap` - 表头映射 - `orderQty` - 订单数量(新增) **逻辑流程:** 1. 提取部件编码 2. 获取BOM需求量(部件工作表中的数量列) 3. 检查库存数据是否存在 4. 计算累计需求量 = 订单数量 × BOM需求量 + 之前累计需求 5. 比较库存和需求: - 库存 >= 累计需求 → 返回 True,更新累计需求量 - 库存 < 累计需求 → 返回 False,记录错误 #### 2.5 修改 `ProcessComponentRecord` 函数签名 **新增参数:** `orderQty As Long` **修改调用:** 传递 `orderQty` 给 `CheckComponentInventory` ### 3. M09_BOMExtractor.bas **修改内容:** #### 3.1 修改 `ReadInputModels` 函数 **当前实现:** 读取2列(生产订单号、产品型号) **注意:** 计划中提到读取3列(包括数量),但当前代码仍使用 `ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, colIdx)).Value`,需要确保 `colIdx` 变量包含第3列(数量列)。 **建议修改:** ```vba ' 确保读取到第3列(数量) ReadInputModels = ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, 3)).Value ``` #### 3.2 修改 `RunBOMExtraction` 主循环 **修改点1:** 提取数量列 ```vba Dim orderQty As Long orderQty = CLng(inputModels(i, 3)) ' Column C: 数量 ``` **修改点2:** 初始化部件处理器时传递库存工作簿 ```vba Dim invWorkbook As Workbook Set invWorkbook = ThisWorkbook ' 现存量在主工作簿中 M08_ComponentProcessor.InitComponentProcessorWithInventory g_Logger, invWorkbook ``` **修改点3:** 传递数量给 `ProcessSingleModel` ```vba Set modelResults = ProcessSingleModel(modelString, g_BOMWorkbook, g_Logger, productionOrderNo, orderQty) ``` #### 3.3 修改 `ProcessSingleModel` 函数签名 **新增参数:** `orderQty As Long` **修改调用:** 传递 `orderQty` 给 `MatchAllMaterialTypesWithValidation` #### 3.4 修改 `MatchAllMaterialTypesWithValidation` 函数签名 **新增参数:** `orderQty As Long` **修改调用:** 传递 `orderQty` 给 `ProcessComponentRecord` ## 数据流程 ### 输入数据 **[产品型号]工作表:** | 生产订单号 | 产品型号 | 数量 | |-----------|---------|------| | PO-001 | YTHN-...| 2 | | PO-003 | YTHN-...| 2 | | PO-006 | YTHN-...| 2 | **[现存量]工作表:** (第3行表头) | ... | 物料编码 | ... | 库存数量 | | ... | COMP001 | ... | 5 | ### 处理逻辑 1. **初始化阶段:** - `InitComponentProcessorWithInventory` 加载库存数据到 `g_InventoryDict` - 创建空的 `g_AccumulatedDemandDict` 用于追踪累计需求 2. **订单处理阶段(按顺序):** - PO-001: 累计需求 = 2×1 + 0 = 2,库存5 >= 2 ✓ → 返回部件 - PO-003: 累计需求 = 2×1 + 2 = 4,库存5 >= 4 ✓ → 返回部件 - PO-006: 累计需求 = 2×1 + 4 = 6,库存5 < 6 ✗ → 返回子件(接头+弹性元件) 3. **错误记录:** - 库存不足时记录错误(Blocking Error) - 未找到库存数据时记录警告(Non-blocking Warning) ### 输出结果 **BOM提取结果:** | 生产订单号 | 原始产品型号 | 物料类型 | 物料名称 | 物料编码 | 物料数量 | 提取备注 | |-----------|-------------|---------|---------|---------|---------|---------| | PO-001 | YTHN-... | 部件 | 部件A | COMP001 | 1 | | | PO-003 | YTHN-... | 部件 | 部件A | COMP001 | 1 | | | PO-006 | YTHN-... | 接头 | 接头B | JOINT01 | 1 | 部件无库存,使用子件 | | PO-006 | YTHN-... | 弹性元件| 元件C | ELEM01 | 1 | 部件无库存,使用子件 | ## 测试要点 ### 功能测试 1. **正常库存场景:** - 准备测试数据:3个订单,库存=5 - 验证前2个订单返回部件 - 验证第3个订单返回子件 2. **边界测试:** - 库存=0,所有订单应返回子件 - 库存充足(>=累计需求),所有订单返回部件 - 库存恰好等于累计需求,应返回部件 3. **异常测试:** - 现存量工作表不存在 → 记录警告,所有订单返回子件 - 部件编码在现存量中不存在 → 记录警告,该订单返回子件 - 数量列为空或非数字 → 应有错误处理 ### 数据验证 1. **累计需求计算:** - 验证累计需求 = 订单数量 × BOM需求量 + 之前累计 - 验证每次处理后累计需求量正确更新 2. **错误报告:** - 检查错误报告工作表是否生成 - 验证库存不足错误正确记录 - 验证警告正确记录 ## 注意事项 ### 关键假设 1. **[现存量]工作表结构:** - 表头在第3行 - 数据从第4行开始 - B列 = 物料编码 - J列 = 库存数量 2. **[产品型号]工作表结构:** - A列 = 生产订单号 - B列 = 产品型号 - C列 = 数量 3. **BOM库[部件]工作表:** - 必须包含"编码"列(部件编码) - 必须包含"数量"列(BOM需求量) ### 已知限制 1. **库存检查时机:** - 库存在初始化时加载一次 - 处理过程中库存不更新(不考虑库存增加) 2. **错误处理:** - 未找到库存数据时返回 False(使用子件) - 不会中断整个流程,继续处理下一个订单 3. **数量列处理:** - 当前代码假设数量列总是存在且为数字 - 如果数量列为空或非数字,可能导致运行时错误 ## 后续改进建议 1. **增强错误处理:** - 在 `ReadInputModels` 中验证数量列是否存在 - 处理数量列为空或非数字的情况 2. **性能优化:** - 如果库存数据很大,考虑只加载需要的部件编码 - 添加日志记录库存使用情况 3. **功能扩展:** - 支持库存实时更新(如果需要) - 支持按批次或其他维度分组计算需求 - 添加库存预留功能(预留库存给特定订单) ## 相关文档 - BOM提取系统架构:`CLAUDE.md` - 库存校验计划:原始计划文档 - 测试用例:需要单独创建 ## 实施验证清单 - [x] M04_Config.bas 添加常量 - [x] M08_ComponentProcessor.bas 添加变量 - [x] M08_ComponentProcessor.bas 实现 LoadInventoryData - [x] M08_ComponentProcessor.bas 重写 CheckComponentInventory - [x] M08_ComponentProcessor.bas 添加 InitComponentProcessorWithInventory - [x] M08_ComponentProcessor.bas 修改 ProcessComponentRecord 签名 - [x] M09_BOMExtractor.bas 修改 RunBOMExtraction(初始化、提取数量) - [x] M09_BOMExtractor.bas 修改 ProcessSingleModel(添加参数) - [x] M09_BOMExtractor.bas 修改 MatchAllMaterialTypesWithValidation(添加参数) - [ ] 验证 ReadInputModels 读取3列(需要确认) - [ ] 端到端测试 - [ ] 错误场景测试