# 库存使用记录 - 修复与测试报告 ## 一、问题与修复概要 | 项目 | 说明 | |------|------| | 问题1 | 修改申请时,同一产品+门店出现多条记录 → 领用多算 | | 修复1 | UpdateApplicationUsageRecords 按 ProductId+StoreId 合并 | | 问题2 | 历史已有多算数据无法人工调整 | | 修复2 | 新增 FixDuplicateUsageRecords 自动修复接口 | | 验证点 | 作废记录不应参与领用统计 | --- ## 二、代码审查结论:作废记录是否会被统计? ### ✅ 结论:作废记录(IsEffective=0)**不会**被计入领用统计 所有涉及 `totalUsage`、领用数量统计的查询均包含 `IsEffective == StatusEnum.有效` 条件: | 文件 | 位置 | 说明 | |------|------|------| | LqInventoryUsageService | GetReceivedBatchIdsAsync、MarkReceivedAsync、CalculateAveragePriceFromInventoryAsync 等 | `x.IsEffective == StatusEnum.有效.GetHashCode()` | | LqInventoryService | 入库前检查、可用库存、平均单价计算 | `x.IsEffective == StatusEnum.有效.GetHashCode()` | | LqProductService | 产品作废检查、库存明细 | `x.IsEffective == StatusEnum.有效.GetHashCode()` | | GetStoreReceiveCostStatistics | whereConditions | `u.F_IsEffective = 1` | | LqBusinessUnitManagerSalaryService | 原生SQL | `WHERE u.F_IsEffective = 1` | | LqDirectorSalaryService | 原生SQL | `WHERE u.F_IsEffective = 1` | | LqStoreManagerSalaryService | 原生SQL | `WHERE u.F_IsEffective = 1` | **领用作废后可用库存会加回去**:作废使用记录后,该记录不再参与 totalUsage 统计,可用库存 = 总库存 - totalUsage 会自动增加。 --- ## 三、数据库现状(MCP 查询结果) - 有效使用记录总数:3240 条 - **存在重复数据**:至少 5 组同一 UsageBatchId+ProductId+StoreId 有多条有效记录,需执行修复接口 示例重复组: - 批次 770197935005631749,产品 763991211127080197,门店 1649328471923847172:2条,总数量6 - 批次 770807754649502981,产品 763992934394627333,门店 1649328471923847187:2条,总数量4 - … --- ## 四、测试清单 ### 1. 修复接口测试 FixDuplicateUsageRecords ```bash # 1) 获取 Token TOKEN=$(curl -s -X POST "http://localhost:2011/api/oauth/Login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e" | jq -r '.data.token') # 2) 执行修复 curl -X POST "http://localhost:2011/api/Extend/LqInventoryUsage/FixDuplicateUsageRecords" \ -H "Authorization: $TOKEN" \ -H "Content-Type: application/json" ``` **验证**: - 返回 `success: true`,`duplicateGroups`、`invalidatedCount` 合理 - 查库:同一 UsageBatchId+ProductId+StoreId 仅剩 1 条有效记录 - 查库:被合并的重复记录 `F_IsEffective = 0` ### 2. 修改申请防重复测试 1. 新建申请,同一产品+门店添加两条(或修改时故意提交重复) 2. 调用 `UpdateApplicationUsageRecords` 提交 3. 查库:该批次下同一产品+门店应只有 1 条有效记录,数量为合并值 ### 3. 作废后不计入统计测试 1. 记录某产品当前可用库存 A 2. 新建申请并领用该产品若干数量,记领用后可用库存 B 3. 作废该领用记录 4. 再次查询可用库存,应恢复为 A(或接近 A,若存在其他领用) ### 4. 领用统计接口一致性测试 - 调用 GetStoreReceiveStatistics、GetStoreReceiveCostStatistics - 与数据库直接 SUM 有效记录对比,结果一致 --- ## 五、执行建议 1. **部署后立即执行**:`POST /api/Extend/LqInventoryUsage/FixDuplicateUsageRecords` 修复历史数据 2. **接口测试**:确保 API 已启动(localhost:2011),按上述 curl 执行 3. **查库验证**:按 mcp-mysql-and-sql-validation 规范,修复后必须查库核对 --- ## 六、实际执行结果(2025-02-13) ### 1. 修复前数据库状态 - 有效使用记录:3240 条 - 无效使用记录:838 条 - **重复组**:5 组(同一 UsageBatchId+ProductId+StoreId 有多条有效记录) | 批次ID | 产品ID | 门店ID | 重复条数 | 总数量 | |--------|--------|--------|----------|--------| | 784301392666821893 | 763979563993662725 | 1649328471923847179 | 2 | 20 | | 787563597701055749 | 763987810846770437 | 1649328471923847176 | 2 | 270 | | 770197935005631749 | 763991211127080197 | 1649328471923847172 | 2 | 6 | | 784209727247615237 | 763991302353192197 | 1649328471923847188 | 2 | 10 | | 770807754649502981 | 763992934394627333 | 1649328471923847187 | 2 | 4 | ### 2. 修复接口调用结果 ```json { "success": true, "message": "修复完成,处理 5 组重复数据,作废 5 条记录", "duplicateGroups": 5, "invalidatedCount": 5 } ``` ### 3. 修复后数据库验证 - **重复组**:0 组 ✓(已清空) - **有效记录**:减少 5 条(每组保留 1 条,作废 1 条) - **无效记录**:843 条(原 838 + 新增 5) - **合并验证**:以批次 787563597701055749 为例,保留 1 条有效(F_UsageQuantity=270, F_TotalAmount=1196.10),另 1 条已作废(F_IsEffective=-1)✓ ### 4. 幂等性验证 再次调用修复接口,返回: ```json { "success": true, "message": "未发现重复数据", "duplicateGroups": 0, "invalidatedCount": 0 } ``` ✓ 幂等性正常,重复执行不会误伤数据。 ### 5. 结论 - 修复接口工作正常 - 合并逻辑正确(数量、金额累加,保留 CreateTime 最早的一条) - 作废记录 (F_IsEffective=-1) 不参与领用统计 - 无需后端代理修复,当前实现正确