# BD_Manual：goods_stock_summary（库存汇总）

> ODS 表：`ods.goods_stock_summary`
> DWD 表：`dwd.dwd_goods_stock_summary`（事实表，无 ex 扩展表）
> API 接口：库存汇总查询（支持 `startTime`/`endTime` 时间窗口参数）
> JSON 路径：`goods_stock_summary.json → data.goodsStockSummaryList`
> 装载方式：事实表按时间窗口增量加载（`DwdLoadTask`）
> ODS 配置：`requires_window=True`，`time_fields=("startTime", "endTime")`
> 代码位置：`apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py`

---

## 1. dwd_goods_stock_summary

| DWD 列名 | 类型 | ODS 源列 | 映射方式 | 业务含义 | 取值范围/示例 |
|----------|------|---------|---------|---------|-------------|
| `site_goods_id` | BIGINT | `sitegoodsid`（ODS DDL 驼峰 → PG 小写） | FACT_MAPPINGS (cast bigint) | 门店商品 ID（PK 之一），关联 `dim_store_goods.site_goods_id` | 飞球商品 ID，如 `3028609051954117` |
| `goods_name` | TEXT | `goodsname` | FACT_MAPPINGS | 商品名称 | 如 `酱香爆珠槟榔`、`百威啤酒` |
| `goods_unit` | TEXT | `goodsunit` | FACT_MAPPINGS | 计量单位 | 如 `包`、`瓶`、`张`、`罐` |
| `goods_category_id` | BIGINT | `goodscategoryid` | FACT_MAPPINGS (cast bigint) | 一级商品分类 ID | 飞球分类 ID |
| `goods_category_second_id` | BIGINT | `goodscategorysecondid` | FACT_MAPPINGS (cast bigint) | 二级商品分类 ID | 飞球分类 ID |
| `category_name` | TEXT | `categoryname` | FACT_MAPPINGS | 一级分类名称 | 如 `槟榔`、`酒水`、`其他` |
| `range_start_stock` | NUMERIC(18,4) | `rangestartstock` | FACT_MAPPINGS (cast numeric) | 期初库存（查询时间窗口起点的库存量） | 如 `100.0000`、`0.0000` |
| `range_end_stock` | NUMERIC(18,4) | `rangeendstock` | FACT_MAPPINGS (cast numeric) | 期末库存（查询时间窗口终点的库存量） | 如 `100.0000`、`0.0000` |
| `range_in` | NUMERIC(18,4) | `rangein` | FACT_MAPPINGS (cast numeric) | 入库数量（时间窗口内的采购/调拨入库总量） | `0.0000` ~ 正数 |
| `range_out` | NUMERIC(18,4) | `rangeout` | FACT_MAPPINGS (cast numeric) | 出库数量（时间窗口内的调拨出库/报损总量） | `0.0000` ~ 正数 |
| `range_sale` | NUMERIC(18,4) | `rangesale` | FACT_MAPPINGS (cast numeric) | 销售数量（时间窗口内的销售出库总量） | `0.0000` ~ 正数 |
| `range_sale_money` | NUMERIC(18,2) | `rangesalemoney` | FACT_MAPPINGS (cast numeric) | 销售金额（元），时间窗口内的销售总金额 | `0.00` ~ 金额值 |
| `range_inventory` | NUMERIC(18,4) | `rangeinventory` | FACT_MAPPINGS (cast numeric) | 盘点调整量（时间窗口内的盘盈/盘亏净量） | 正数（盘盈）或负数（盘亏） |
| `current_stock` | NUMERIC(18,4) | `currentstock` | FACT_MAPPINGS (cast numeric) | 当前库存（API 返回时的实时库存量） | `0.0000` ~ 正数 |
| `site_id` | BIGINT | `site_id` | 自动映射 | 门店 ID（ETL 注入） | 飞球门店 ID |
| `tenant_id` | BIGINT | `tenant_id` | 自动映射 | 租户 ID（ETL 注入） | 飞球租户 ID |
| `fetched_at` | TIMESTAMPTZ | `fetched_at` | 自动映射 | ETL 采集时间戳（PK 之一），标识本次快照的采集时间 | ISO 时间戳 |

---

## 2. 主键说明

主键为 `(site_goods_id, fetched_at)` 复合键。同一商品在不同采集时间窗口会产生多条记录，每条记录代表该时间窗口内的库存汇总快照。

---

## 3. ODS 列名映射说明

ODS DDL 中列名使用驼峰式（如 `siteGoodsId`），但 PostgreSQL 在无引号时自动小写化为 `sitegoodsid`。FACT_MAPPINGS 中使用带引号的 ODS 列名（如 `"siteGoodsId"`）以正确引用。

---

## 4. DWS 下游

- `dws.dws_goods_stock_daily_summary`：日度库存汇总
- `dws.dws_goods_stock_weekly_summary`：周度库存汇总（ISO 周）
- `dws.dws_goods_stock_monthly_summary`：月度库存汇总

---

## 5. 代码引用

- FACT_MAPPINGS：`dwd_load_task.py` → `FACT_MAPPINGS["dwd.dwd_goods_stock_summary"]`
- TABLE_MAP：`"dwd.dwd_goods_stock_summary" → "ods.goods_stock_summary"`
- ODS 任务配置：`tasks/ods/ods_tasks.py` → `OdsTaskSpec("ODS_GOODS_STOCK_SUMMARY", requires_window=True, time_fields=("startTime", "endTime"))`
- DWS 任务：`tasks/dws/goods_stock_daily_task.py`、`goods_stock_weekly_task.py`、`goods_stock_monthly_task.py`
