# 团购套餐定义（QueryPackageCouponList） → group_buy_packages 字段映射

> 生成时间：2026-02-14

## 端点信息

| 属性 | 值 |
|------|-----|
| 接口路径 | `PackageCoupon/QueryPackageCouponList` |
| 请求方法 | POST |
| ODS 对应表 | `ods.group_buy_packages` |
| JSON 数据路径 | `data.packageCouponList` |

## 字段映射

| JSON 字段 | ODS 列名 | 类型转换 | 说明 |
|-----------|----------|----------|------|
| id | id | int→BIGINT（`parse_int`） | 门店侧套餐 ID，本文件内部的主键 |
| package_id | package_id | int→BIGINT（`parse_int`） | “上层套餐 ID” 或“总部/系统级套餐 ID” |
| package_name | package_name | string→TEXT（原样） | 团购套餐名称，用于前台展示和核销界面 |
| selling_price | selling_price | float→NUMERIC(18,2)（`parse_decimal`） | 语义上应该是“团购售卖价”（顾客在平台购买券时的成交价格） |
| coupon_money | coupon_money | float→NUMERIC(18,2)（`parse_decimal`） | 券面值或内部结算面值，表示该套餐在门店侧对应的金额额度 |
| date_type | date_type | int→INT（`parse_int`） | 来自 JSON 导出的原始字段，用于保留业务取值 |
| date_info | date_info | string→TEXT（原样） | 预留字段，通常用来存储更细粒度的日期信息，如具体日期列表、节假日特殊规则（可能是 JSON 字符串或编码） |
| start_time | start_time | string→TIMESTAMP（`parse_timestamp`） | 套餐开始生效的日期时间 |
| end_time | end_time | string→TIMESTAMP（`parse_timestamp`） | 套餐失效的日期时间（到这个时间点后不可使用） |
| start_clock | start_clock | string→TEXT（原样） | 每日可用起始时间点（第一段） |
| end_clock | end_clock | string→TEXT（原样） | 每日可用的结束时间点（第一段） |
| add_start_clock | add_start_clock | string→TEXT（原样） | 附加可用时间段的起始时间（第二段） |
| add_end_clock | add_end_clock | string→TEXT（原样） | 附加时段结束时间，多数情况配合 "00:00:00" 或 "10:00:00" 使用 |
| duration | duration | int→INT（`parse_int`） | 套餐内包含的时长（秒） |
| usable_count | usable_count | int→INT（`parse_int`） | 可使用次数上限 |
| usable_range | usable_range | int→INT（`parse_int`） | 一般用于文字描述可用日期范围（例如“周一至周五”） |
| table_area_id | table_area_id | int→BIGINT（`parse_int`） | 原始设计应为“单一台区 ID”，当套餐只限一个区域可以用这个字段存储 |
| table_area_name | table_area_name | string→TEXT（原样） | 套餐适用的“门店台区名称”，用于显示和筛选 |
| table_area_id_list | table_area_id_list | object→JSONB（原样存储） | 用来存放具体台区 ID 列表（例如 "1,2,3"），实现更细粒度的台桌限制 |
| tenant_table_area_id | tenant_table_area_id | int→BIGINT（`parse_int`） | 与 table_area_id 类似，是租户层级的台区 ID，原本用于单区选择 |
| tenant_table_area_id_list | tenant_table_area_id_list | object→JSONB（原样存储） | 实际代表“台区集合 ID”或“租户台区配置 ID”，用来限制套餐可用的台区范围 |
| site_id | site_id | int→BIGINT（`parse_int`） | 门店 ID |
| site_name | site_name | string→TEXT（原样） | 门店名称 |
| tenant_id | tenant_id | int→BIGINT（`parse_int`） | 租户 ID（品牌/商户 ID） |
| card_type_ids | card_type_ids | object→JSONB（原样存储） | 原意是“适用会员卡类型 ID 列表”，例如某套餐只允许某几种会员卡使用，可以在此配置 |
| group_type | group_type | int→INT（`parse_int`） | 来自 JSON 导出的原始字段，用于保留业务取值 |
| system_group_type | system_group_type | int→INT（`parse_int`） | 来自 JSON 导出的原始字段，用于保留业务取值 |
| type | type | int→INT（`parse_int`） | 内部业务子类型，具体含义需要结合系统文档 |
| effective_status | effective_status | int→INT（`parse_int`） | 1：13 条 |
| is_enabled | is_enabled | int→INT（`parse_int`） | 启用状态 |
| is_delete | is_delete | int→INT（`parse_int`） | 逻辑删除标志 |
| max_selectable_categories | max_selectable_categories | int→INT（`parse_int`） | 来自 JSON 导出的原始字段，用于保留业务取值 |
| area_tag_type | area_tag_type | int→INT（`parse_int`） | 1 很可能代表“按台区标签限制”，例如 A区、中八区、包厢、KTV 等 |
| creator_name | creator_name | string→TEXT（原样） | 创建人信息，一般包含“角色：姓名” |
| create_time | create_time | string→TIMESTAMP（`parse_timestamp`） | 该套餐在系统中创建的时间 |
| is_first_limit | is_first_limit | bool→BOOLEAN | 是否限首次使用（新增字段） |
| sort | sort | int→INT（`parse_int`） | 排序权重（新增字段） |
| tenantcouponsaleorderitemid | tenantcouponsaleorderitemid | int→BIGINT（`parse_int`） | 租户券销售订单项 ID（新增字段） |

## ETL 补充字段

| ODS 列名 | 生成逻辑 |
|-----------|----------|
| content_hash | 对业务字段（排除 ETL 元数据列）计算 SHA-256，用于变更检测与去重 |
| source_file | 固定值：`group_buy_packages.json`，标识原始导出文件 |
| source_endpoint | API 端点路径，如 `PackageCoupon/QueryPackageCouponList` |
| fetched_at | ETL 入库时间戳（`TIMESTAMPTZ DEFAULT now()`） |
| payload | 完整原始 JSON 记录快照（`JSONB NOT NULL`），用于回溯与二次解析 |

## 类型转换规则

- **时间戳**：通过 `TypeParser.parse_timestamp()` 转换，支持 ISO 字符串和 Unix 毫秒时间戳，自动处理时区
- **金额**：通过 `TypeParser.parse_decimal(value, scale=2)` 转换，`ROUND_HALF_UP` 四舍五入
- **整数**：通过 `TypeParser.parse_int()` 转换，`None` 保持为 `NULL`
- **字符串**：原样保留，`None` / 空字符串均存为 `NULL` 或空文本
- **布尔值**：API 返回 `true/false`，ODS 存为 `BOOLEAN` 或 `INT`（0/1）
- **JSONB**：`siteProfile`、`payload` 等复合对象直接以 `JSONB` 类型存储
