# 库存汇总报表(GetGoodsStockReport) > 自动生成于 2026-02-13 | 数据来源:实时 API ## 基本信息 | 属性 | 值 | |------|-----| | 接口路径 | `TenantGoods/GetGoodsStockReport` | | 完整 URL | `https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsStockReport` | | 请求方法 | `POST` | | Content-Type | `application/json` | | 鉴权方式 | Bearer Token(`Authorization` 头) | | ODS 对应表 | `goods_stock_summary` | | 分页方式 | `page` + `limit`(最大 100) | | 时间范围 | 需要(startTime / endTime) | ## 请求参数 | 参数名 | 类型 | 示例值 | 说明 | |--------|------|--------|------| | `siteId` | int | `2790685415443269` | 门店 ID | | `startTime` | string | `"2026-02-01 08:00:00"` | 查询起始时间 | | `endTime` | string | `"2026-02-13 08:00:00"` | 查询结束时间 | | `page` | int | `1` | 页码(从 1 开始) | | `limit` | int | `100` | 每页条数(最大 100) | ## 响应字段(共 14 个) | # | 字段名 | 类型 | 示例值 | |---|--------|------|--------| | 1 | `siteGoodsId` | int | 3089190204491141 | | 2 | `goodsName` | string | '小合味道' | | 3 | `goodsUnit` | string | '桶' | | 4 | `goodsCategoryId` | int | 2791941988405125 | | 5 | `goodsCategorySecondId` | int | 2793236829620037 | | 6 | `rangeStartStock` | int | 0 | | 7 | `rangeEndStock` | int | 22 | | 8 | `rangeIn` | int | 24 | | 9 | `rangeOut` | int | -2 | | 10 | `rangeInventory` | int | 0 | | 11 | `rangeSale` | int | 2 | | 12 | `rangeSaleMoney` | float | 16.0 | | 13 | `currentStock` | int | 22 | | 14 | `categoryName` | string | '零食' | ## 详细字段分析 > 以下内容迁移自旧版 `goods_stock_summary-Analysis.md`,包含字段的业务含义、枚举值、跨表关联等详细说明。 每个元素就是某个 门店商品(siteGoodsId)在一个查询时间区间内的库存汇总。 二、字段分组说明(含类型 / 是否枚举 / 枚举值) 1. 商品主键与基本信息 1.1 siteGoodsId 类型:int 特征: 161 条记录中 161 个唯一值。 与 “门店商品档案” (20251110_051132_…1.json) 中 orderGoodsList 里的 id 完全一一对应。 含义: 门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识。 关联: 库存汇总.siteGoodsId = 门店商品档案.id 也与库存变动记录(库存变化记录1)里的 siteGoodsId 对应(库存流水的外键)。 1.2 goodsName 类型:string 特征: 每条记录一个商品名,共 161 个不同值(与 siteGoodsId 一一对应)。 例:"东方树叶", "红烧牛肉面", "薯片" 等。 含义: 商品名称,冗余于门店商品档案的 goods_name。 结构意义: 方便直接阅读汇总报表,无需再次联表取商品档案。 1.3 goodsUnit 类型:string 特征: 典型取值(枚举): "包":59 条 "瓶":46 条 "个":17 条 "份":13 条 "根":10 条 "盒", "杯", "桶", "盘", "支" 等 与门店商品档案中的 unit 字段完全一致。 含义: 商品的计量单位(售卖单位)。 小结:siteGoodsId + goodsName + goodsUnit 在结构上确定一条“门店商品”的维度信息,和“门店商品档案”的字段是完全对齐的。 2. 分类维度字段 2.1 goodsCategoryId 类型:int 特征: 非空,161 条记录中有 9 个不同的 ID。 每一个 goodsCategoryId 对应 唯一一个 categoryName(一对一)。 含义: 一级商品分类 ID。 枚举映射(由数据直接推得): 2791941988405125 → "零食" 2790683528350539 → "酒水" 2792062778003333 → "香烟" 2793217944864581 → "其他" 2791942087561093 → "雪糕" 2790683528350535 → "器材" 2793220945250117 → "小吃" 2790683528350533 → "槟榔" 2790683528350545 → "果盘" (ID 是系统内部编码,你这边可以当“分类主键”。) 2.2 goodsCategorySecondId 类型:int 特征: 非空,有 14 个不同的 ID。 每个二级 ID 对应一个更细的类目(比如不同品牌/系列),但名称在本文件中没有给出。 含义: 二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类。 关联: 在库存变动类 JSON / 商品分类 JSON(之前看到的分类导出)中,有完整的分类树,可通过这些 ID 找回二级分类名称。 2.3 categoryName 类型:string 特征: 枚举值恰好 9 个,分别是: "零食", "酒水", "香烟", "其他", "雪糕", "器材", "小吃", "槟榔", "果盘" 与 goodsCategoryId 一一对应。 含义: 一级分类名称,属于冗余字段,用于直接展示。 结构结论: 分类主键:goodsCategoryId(一级)+ goodsCategorySecondId(二级) 分类名称:categoryName 仅给了一级中文名,二级名需要到分类表/门店商品档案中再查。 3. 库存数量相关字段(全部为整数) 3.1 rangeStartStock 类型:int 特征: 非空,有 61 个不同数值。 示例值:0, 1, 2, 4, 7, 8, 29 ... 含义: 查询区间 起始时刻 的库存数量(期初库存)。 结构作用: 与下方各类“变动量”一起构成库存平衡公式。 3.2 rangeEndStock 类型:int 特征: 非空,有 61 个不同数值。 示例值: 0, 1, 5, 7, 8, 16 ... 含义: 查询区间 结束时刻 的库存数量(期末库存)。 3.3 rangeIn 类型:int 特征: 非空,多为正整数或 0。 示例值:0, 30, 90, 450 ... 含义: 查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等。 3.4 rangeOut 类型:int 特征: 有 64 个不同值,且全部为 0 或负数: 0(36次)、-1、-2、-3、-4、-7、-8、-14、-35 …… 含义: 查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售)。 结构公式验证(关键): 对每一条记录,都满足: rangeStartStock + rangeIn + rangeInventory + rangeOut = rangeEndStock 即:期初 + 入库 + 盘点调整 + 出库 = 期末 当前数据中 rangeInventory 全为 0,那么简化为: rangeStartStock + rangeIn + rangeOut = rangeEndStock。 3.5 rangeInventory 类型:int 特征: 所有 161 条记录均为 0。 含义: 查询区间内的 盘点调整净变动量(盘盈–盘亏)。 当前数据状态: 这段时间内没有发生盘点或盘点对库存无净影响,所以全为 0。 结构意义: 在有盘点的场景,这个字段会承担“非正常出入库”的调整职责,并参与上面的平衡公式。 3.6 currentStock 类型:int 特征: 非空,61 个不同值。 示例值:0, 1, 2, 3, 4, 5, 6, 7, 10, 14 ... 大部分记录里,currentStock 与 rangeEndStock 相等;但有 17 条 存在差异(通常是小差值,例如 rangeEndStock=74, currentStock=72)。 含义(推断): 导出时刻的实时库存数量。 与 rangeEndStock 关系: rangeEndStock 是“查询时间段结束瞬间”的库存; currentStock 是“导出时当前瞬间”的库存。 这说明:在查询区间之后,可能又发生了一些出入库,导致当前库存与期末库存略有差异。 结构小结: (rangeStartStock, rangeIn, rangeOut, rangeInventory, rangeEndStock) 构成一个严格的库存平衡关系。 currentStock 则是另一个时间点的库存快照,在结构上属于“附加状态字段”,不参与那个公式。 4. 销量与销售金额(汇总) 4.1 rangeSale 类型:int 特征: 非空,有 65 个不同的整数。 示例:0, 1, 2, 3, 4, 5, 6, 8, 13, 14 ... 含义: 查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等)。 与 rangeOut 的关系(结构上): 对绝大多数以“销售出库”为主的商品,rangeOut 的绝对值与 rangeSale 大致一致(也可能有非销售出库,比如报损/调拨),这一点需要结合库存变动明细来判断,但属于业务层逻辑,这里不展开。 4.2 rangeSaleMoney 类型:float 特征: 非空,有 102 个不同的浮点值。 示例:0.0, 48.0, 30.0, 40.0, 280.0, 60.0, 50.0, 15.0 ... 很多数值看起来是整数金额,但用 float 存储,为以后兼容小数价格预留空间。 含义: 查询区间内,该商品销售的 金额小计(按商品维度汇总)。 结构特征(不做业绩解读,只谈结构): 对于有销量的记录,可以通过简单比例验证: 单品成交单价 ≈ rangeSaleMoney / rangeSale 如某商品记录: rangeSale = 62 rangeSaleMoney = 744.0 求比值 ≈ 12.0 → 对应门店商品档案中的 sale_price。 也就是说:在结构上,rangeSaleMoney 与 “汇总数量 × 单价” 对应关系非常一致,说明这个字段确实是商品维度的销售金额汇总。 这里我仅确认字段之间的 计量逻辑与结构关系,不做任何“好/坏”的业务评价。 三、与其它 JSON 的关联关系(结构层面) 1. 与“门店商品档案” JSON 的关系 通过实际比对: 库存汇总.siteGoodsId = 门店商品档案.orderGoodsList.id 库存汇总.goodsName = 门店商品档案.goods_name 库存汇总.goodsUnit = 门店商品档案.unit 库存汇总.goodsCategoryId = 门店商品档案.goods_category_id 库存汇总.goodsCategorySecondId = 门店商品档案.goods_second_category_id 结构含义: 门店商品档案:静态维度表,包含商品的售价、成本、是否计库存、分类名称等。 库存汇总:针对同一批 id 做的“某一时间范围内的库存+销量汇总”。 因此,你可以把“库存汇总”看成是对“门店商品档案”的一个衍生事实表,按照商品维度聚合库存与销售信息。 2. 与“库存变化记录”(库存流水)的关系 虽然你这份导出里“库存变化记录”在另外一个 JSON 中(字段里有 siteGoodsId、stockType 等),但从字段名和使用方式可以推断: 库存变化记录: 粒度:一条库存变动(一笔入库/出库/盘点等)。 重要字段: siteGoodsId:对应库存汇总中的 siteGoodsId。 stockType:入库、出库、盘点等类型枚举。 changeNum:每次变动数量。 库存汇总: 粒度:某商品在查询区间内的汇总。 字段:rangeIn, rangeOut, rangeInventory 等就是对库存变化记录按 siteGoodsId + 时间区间 汇总出来的结果。 结构关系可以概括为: 库存变化记录(明细表) ↓ 按 siteGoodsId + 时间范围聚合 库存汇总(汇总表) 这使得你在需要追查明细时,可以从“汇总 → 明细”下钻。 3. 与“门店销售记录”的关系 从字段设计看: 门店销售记录中有: site_goods_id:门店商品 ID ledger_amount:单条销售明细金额 ledger_count:销售数量 库存汇总中有: siteGoodsId:门店商品 ID rangeSale:总销售数量(在时间范围内) rangeSaleMoney:总销售金额(在时间范围内) 结构上可以理解为: 门店销售记录 是 每一个销售明细; 库存汇总 是在某时间段对这些明细按商品维度做的 汇总。 两者之间通过 siteGoodsId/site_goods_id 联接,同时需要根据时间条件约束订单时间,这一点在结构上是清晰的。 4. 与商品分类树(库存变化记录2 / 分类 JSON)的关系 在之前分类 JSON 中,你有一个分类树结构(有 id, pid, category_name, categoryBoxes 等): 库存汇总.goodsCategoryId 对应 分类树中的某个一级分类 id。 库存汇总.goodsCategorySecondId 对应其子分类(分类树中某个 pid=一级分类id 的节点)。 categoryName 与分类树中的 category_name 对应(一级节点)。 结构关系: 分类树 JSON (全局分类维表) ↑ ↑ goodsCategoryId goodsCategorySecondId ↑ ↑ 库存汇总 (事实表) 四、结构层面可以注意的一些“关系和约束” 全部是字段设计/数值关系层面,不涉及盈利或经营分析: 库存平衡公式存在且逐条成立 对每一条记录,都可以验证: rangeStartStock + rangeIn + rangeInventory + rangeOut = rangeEndStock 当前导出中 rangeInventory = 0,所以简化公式为: rangeStartStock + rangeIn + rangeOut = rangeEndStock 严格成立说明: 系统在生成库存汇总时,确实是从明细出入库数据做了完整计算,而不是凭输入数据临时凑数。 出库量采用“负数”表示 rangeOut 不再定义为“出库数量(正数)”,而是直接记 负数。 好处是:公式中无需写“–出库量”,直接做代数求和。 这个习惯在后续做数据集成或迁移时需要注意,避免重复取绝对值/重复取负。 区分“期末库存”与“当前库存”两个时间点 rangeEndStock:查询时间段的期末库存。 currentStock:导出那一刻的库存快照。 二者不一定相等(有部分记录存在差 1–4 的差值),说明结构上清晰区分了查询区间和当前状态。 汇总粒度清晰:每个 siteGoodsId 仅一条记录 siteGoodsId 在本文件中不重复,说明这是按商品聚合后的汇总层,没有再分仓库、批次、货位等维度。 如果未来需要按仓/货位维度汇总,结构可能会出现类似 warehouseId 之类的新字段,从这份数据来看目前没有。 金额与数量之间存在一致的单价模式 对于 rangeSale > 0 的商品,rangeSaleMoney / rangeSale 与门店商品档案中的 sale_price 一致,这只是结构上的一致性检查: 说明 rangeSaleMoney 并不是某种复杂的计算结果,而是“销售数量 × 单价”的汇总。 这在系统设计上有利于做“金额与数量对账”。 分类 ID 与中文名称一一对应 goodsCategoryId 和 categoryName 的关系是一对一,没有出现“同一 categoryName 对应多 ID”的情况。 这说明在该门店中,一级分类的结构比较干净,没有重复创建多个 ID 对应相同名称的情况;对你的后续系统对接来说,这一层结构相对简单,只需要维护一套映射即可。 五、小结 20251110_043308_库存汇总.json 本质上是: 以 门店商品(siteGoodsId) 为粒度, 在某个查询时间范围内,对该商品的: 期初库存(rangeStartStock) 入库量(rangeIn) 出库量(rangeOut,负数) 盘点调整(rangeInventory) 期末库存(rangeEndStock) 销售数量(rangeSale) 销售金额(rangeSaleMoney) 做了一次结构化汇总; 同时给出了当前时点库存快照(currentStock),并冗余了商品名、单位、一级分类名等维度信息。 在全局数据模型里,它与 门店商品档案 / 库存变动明细 / 门店销售明细 / 分类树 等文件通过主键(siteGoodsId、分类 ID)和时间条件构成一套“明细–汇总–维度”相互嵌套的结构,这对于后续做数据迁移、数据仓库建模或者跨系统字段映射都比较有价值。