重构数据引擎和报表引擎

This commit is contained in:
2026-06-11 13:06:54 +08:00
parent 285a0fc632
commit 419473f266
53 changed files with 8434 additions and 375 deletions

View File

@@ -0,0 +1,117 @@
-- ============================================================
-- 报表系统表 - 新增 tenant_id 迁移脚本
-- 为已存在的5张报表系统表添加租户隔离字段
-- 执行前请确认当前数据库中表是否存在
-- ============================================================
-- ----------------------------------------------------------
-- 1. report_business_config (业务配置表)
-- ----------------------------------------------------------
-- 添加 tenant_id 列
ALTER TABLE IF EXISTS report_business_config
ADD COLUMN IF NOT EXISTS tenant_id BIGINT NOT NULL DEFAULT 0;
-- 重建唯一索引(加入 tenant_id
DROP INDEX IF EXISTS idx_business_code;
CREATE UNIQUE INDEX IF NOT EXISTS idx_business_code
ON report_business_config (tenant_id, business_code);
COMMENT ON COLUMN report_business_config.tenant_id IS '租户ID';
-- ----------------------------------------------------------
-- 2. report_report_config (报表配置表)
-- ----------------------------------------------------------
-- 添加 tenant_id 列
ALTER TABLE IF EXISTS report_report_config
ADD COLUMN IF NOT EXISTS tenant_id BIGINT NOT NULL DEFAULT 0;
-- 重建唯一约束(加入 tenant_id
ALTER TABLE IF EXISTS report_report_config
DROP CONSTRAINT IF EXISTS uk_business_report_code;
ALTER TABLE IF EXISTS report_report_config
ADD CONSTRAINT uk_business_report_code UNIQUE (tenant_id, business_code, report_code);
-- 重建索引
DROP INDEX IF EXISTS idx_report_business_code;
CREATE INDEX IF NOT EXISTS idx_report_business_code
ON report_report_config (tenant_id, business_code);
COMMENT ON COLUMN report_report_config.tenant_id IS '租户ID';
-- ----------------------------------------------------------
-- 3. report_field_config (字段配置表)
-- ----------------------------------------------------------
-- 添加 tenant_id 列
ALTER TABLE IF EXISTS report_field_config
ADD COLUMN IF NOT EXISTS tenant_id BIGINT NOT NULL DEFAULT 0;
-- 重建唯一约束(加入 tenant_id
ALTER TABLE IF EXISTS report_field_config
DROP CONSTRAINT IF EXISTS uk_business_report_field_code;
ALTER TABLE IF EXISTS report_field_config
ADD CONSTRAINT uk_business_report_field_code UNIQUE (tenant_id, business_code, report_code, field_code);
-- 重建索引
DROP INDEX IF EXISTS idx_field_business_report;
CREATE INDEX IF NOT EXISTS idx_field_business_report
ON report_field_config (tenant_id, business_code, report_code);
DROP INDEX IF EXISTS idx_field_data_type;
CREATE INDEX IF NOT EXISTS idx_field_data_type
ON report_field_config (tenant_id, data_type);
DROP INDEX IF EXISTS idx_field_field_role;
CREATE INDEX IF NOT EXISTS idx_field_field_role
ON report_field_config (tenant_id, field_role);
COMMENT ON COLUMN report_field_config.tenant_id IS '租户ID';
-- ----------------------------------------------------------
-- 4. report_extract_config (抽取配置表)
-- ----------------------------------------------------------
-- 添加 tenant_id 列
ALTER TABLE IF EXISTS report_extract_config
ADD COLUMN IF NOT EXISTS tenant_id BIGINT NOT NULL DEFAULT 0;
-- 重建唯一约束(加入 tenant_id
ALTER TABLE IF EXISTS report_extract_config
DROP CONSTRAINT IF EXISTS uk_business_report_extract_code;
ALTER TABLE IF EXISTS report_extract_config
ADD CONSTRAINT uk_business_report_extract_code UNIQUE (tenant_id, business_code, report_code, extract_code);
-- 重建索引
DROP INDEX IF EXISTS idx_extract_business_report;
CREATE INDEX IF NOT EXISTS idx_extract_business_report
ON report_extract_config (tenant_id, business_code, report_code);
COMMENT ON COLUMN report_extract_config.tenant_id IS '租户ID';
-- ----------------------------------------------------------
-- 5. report_extract_log (抽取记录表)
-- ----------------------------------------------------------
-- 添加 tenant_id 列
ALTER TABLE IF EXISTS report_extract_log
ADD COLUMN IF NOT EXISTS tenant_id BIGINT NOT NULL DEFAULT 0;
-- 重建唯一约束(加入 tenant_id
ALTER TABLE IF EXISTS report_extract_log
DROP CONSTRAINT IF EXISTS uk_extract_keys;
ALTER TABLE IF EXISTS report_extract_log
ADD CONSTRAINT uk_extract_keys UNIQUE (tenant_id, business_code, report_code, extract_code, stat_date);
-- 重建索引
DROP INDEX IF EXISTS idx_extract_log_business_report;
CREATE INDEX IF NOT EXISTS idx_extract_log_business_report
ON report_extract_log (tenant_id, business_code, report_code);
DROP INDEX IF EXISTS idx_extract_log_stat_date;
CREATE INDEX IF NOT EXISTS idx_extract_log_stat_date
ON report_extract_log (tenant_id, stat_date);
COMMENT ON COLUMN report_extract_log.tenant_id IS '租户ID';

301
sql/report_common_ddl.sql Normal file
View File

@@ -0,0 +1,301 @@
-- ============================================================
-- 通用报表公共包 - 系统表 DDL
-- 业务隔离、多业务支持、表/字段 100% 配置化
-- ============================================================
-- ----------------------------------------------------------
-- 1. 业务配置表 (business_config)
-- ----------------------------------------------------------
CREATE TABLE IF NOT EXISTS report_business_config (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
business_code VARCHAR(64) NOT NULL,
business_name VARCHAR(128) NOT NULL,
description TEXT DEFAULT '',
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
config JSONB DEFAULT '{}',
creator VARCHAR(64) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updater VARCHAR(64) DEFAULT '',
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
COMMENT ON TABLE report_business_config IS '报表业务配置表';
COMMENT ON COLUMN report_business_config.tenant_id IS '租户ID';
COMMENT ON COLUMN report_business_config.business_code IS '业务编码(唯一标识)';
COMMENT ON COLUMN report_business_config.business_name IS '业务名称';
COMMENT ON COLUMN report_business_config.description IS '业务描述';
COMMENT ON COLUMN report_business_config.status IS '状态: ACTIVE启用/INACTIVE停用';
COMMENT ON COLUMN report_business_config.config IS '业务级配置(JSON),如默认数据源等';
CREATE UNIQUE INDEX IF NOT EXISTS idx_business_code ON report_business_config (tenant_id, business_code);
-- ----------------------------------------------------------
-- 2. 报表配置表 (report_config)
-- ----------------------------------------------------------
CREATE TABLE IF NOT EXISTS report_report_config (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
business_code VARCHAR(64) NOT NULL,
report_code VARCHAR(64) NOT NULL,
report_name VARCHAR(128) NOT NULL,
description TEXT DEFAULT '',
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
stat_table_name VARCHAR(128) NOT NULL,
stat_table_comment VARCHAR(256) DEFAULT '',
date_field VARCHAR(64) DEFAULT 'stat_date',
primary_keys JSONB DEFAULT '["id"]'::jsonb,
conflict_keys JSONB DEFAULT '["stat_date"]'::jsonb,
config JSONB DEFAULT '{}',
creator VARCHAR(64) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updater VARCHAR(64) DEFAULT '',
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
CONSTRAINT uk_business_report_code UNIQUE (tenant_id, business_code, report_code)
);
COMMENT ON TABLE report_report_config IS '报表配置表';
COMMENT ON COLUMN report_report_config.tenant_id IS '租户ID';
COMMENT ON COLUMN report_report_config.business_code IS '所属业务编码';
COMMENT ON COLUMN report_report_config.report_code IS '报表编码(唯一标识)';
COMMENT ON COLUMN report_report_config.report_name IS '报表名称';
COMMENT ON COLUMN report_report_config.stat_table_name IS '统计宽表表名';
COMMENT ON COLUMN report_report_config.stat_table_comment IS '统计宽表注释';
COMMENT ON COLUMN report_report_config.date_field IS '日期字段名';
COMMENT ON COLUMN report_report_config.primary_keys IS '主键字段列表(JSON数组)';
COMMENT ON COLUMN report_report_config.conflict_keys IS '冲突键(用于ON CONFLICT upsert)';
COMMENT ON COLUMN report_report_config.config IS '报表级配置(JSON)';
CREATE INDEX IF NOT EXISTS idx_report_business_code ON report_report_config (tenant_id, business_code);
-- ----------------------------------------------------------
-- 3. 报表字段配置表 (report_field_config)
-- 维度、指标、筛选字段 100% 配置化
-- ----------------------------------------------------------
CREATE TABLE IF NOT EXISTS report_field_config (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
business_code VARCHAR(64) NOT NULL,
report_code VARCHAR(64) NOT NULL,
field_code VARCHAR(64) NOT NULL,
field_name VARCHAR(128) NOT NULL,
field_type VARCHAR(32) NOT NULL,
data_type VARCHAR(32) NOT NULL DEFAULT 'STRING',
field_role VARCHAR(32) NOT NULL,
is_aggregatable BOOLEAN DEFAULT FALSE,
is_filterable BOOLEAN DEFAULT TRUE,
is_queryable BOOLEAN DEFAULT TRUE,
is_sortable BOOLEAN DEFAULT TRUE,
default_aggregate VARCHAR(32) DEFAULT '',
valid_aggregates JSONB DEFAULT '[]'::jsonb,
filter_operators JSONB DEFAULT '["=","!=",">","<",">=","<=","IN","LIKE","BETWEEN"]'::jsonb,
expression VARCHAR(512) DEFAULT '',
expression_type VARCHAR(32) DEFAULT '',
format_pattern VARCHAR(64) DEFAULT '',
unit VARCHAR(32) DEFAULT '',
dict_code VARCHAR(64) DEFAULT '',
sort_order INT DEFAULT 0,
group_name VARCHAR(64) DEFAULT '',
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
creator VARCHAR(64) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updater VARCHAR(64) DEFAULT '',
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
CONSTRAINT uk_business_report_field_code UNIQUE (tenant_id, business_code, report_code, field_code)
);
COMMENT ON TABLE report_field_config IS '报表字段配置表(维度/指标/筛选)';
COMMENT ON COLUMN report_field_config.tenant_id IS '租户ID';
COMMENT ON COLUMN report_field_config.business_code IS '所属业务编码';
COMMENT ON COLUMN report_field_config.report_code IS '所属报表编码';
COMMENT ON COLUMN report_field_config.field_code IS '字段编码(唯一)';
COMMENT ON COLUMN report_field_config.field_name IS '字段显示名称';
COMMENT ON COLUMN report_field_config.field_type IS '字段类型: STRING/INT/FLOAT/DATE/DATETIME/JSONB';
COMMENT ON COLUMN report_field_config.data_type IS '数据类型: DIMENSION维度/INDICATOR指标/FILTER筛选';
COMMENT ON COLUMN report_field_config.field_role IS '字段角色: DIMENSION维度/INDICATOR指标/FILTER筛选/FILTER_ONLY仅筛选';
COMMENT ON COLUMN report_field_config.is_aggregatable IS '是否可统计(sum/count/avg)';
COMMENT ON COLUMN report_field_config.is_filterable IS '是否可筛选';
COMMENT ON COLUMN report_field_config.is_queryable IS '是否可查询';
COMMENT ON COLUMN report_field_config.is_sortable IS '是否可排序';
COMMENT ON COLUMN report_field_config.default_aggregate IS '默认聚合方式: SUM/COUNT/AVG/MAX/MIN';
COMMENT ON COLUMN report_field_config.valid_aggregates IS '支持的聚合方式(JSON数组)';
COMMENT ON COLUMN report_field_config.filter_operators IS '支持的筛选操作符(JSON数组)';
COMMENT ON COLUMN report_field_config.expression IS '计算表达式(如退款率=退款金额/销售额*100)';
COMMENT ON COLUMN report_field_config.expression_type IS '表达式类型: CALCULATED衍生/ORIGINAL原始';
COMMENT ON COLUMN report_field_config.format_pattern IS '格式化模式(如 #,##0.00%)';
COMMENT ON COLUMN report_field_config.unit IS '单位(如元/件/%)';
COMMENT ON COLUMN report_field_config.dict_code IS '字典编码(用于下拉选项)';
COMMENT ON COLUMN report_field_config.sort_order IS '排序顺序';
COMMENT ON COLUMN report_field_config.group_name IS '字段分组名称';
CREATE INDEX IF NOT EXISTS idx_field_business_report ON report_field_config (business_code, report_code);
CREATE INDEX IF NOT EXISTS idx_field_data_type ON report_field_config (data_type);
CREATE INDEX IF NOT EXISTS idx_field_field_role ON report_field_config (field_role);
-- ----------------------------------------------------------
-- 4. 数据抽取配置表 (extract_config)
-- 100% 配置化,不硬编码任何抽取逻辑
-- ----------------------------------------------------------
CREATE TABLE IF NOT EXISTS report_extract_config (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
business_code VARCHAR(64) NOT NULL,
report_code VARCHAR(64) NOT NULL,
extract_code VARCHAR(64) NOT NULL,
extract_name VARCHAR(128) NOT NULL,
source_table_name VARCHAR(128) NOT NULL,
source_table_alias VARCHAR(64) DEFAULT '',
target_table_name VARCHAR(128) NOT NULL,
is_enabled BOOLEAN DEFAULT TRUE,
extract_type VARCHAR(32) NOT NULL DEFAULT 'FULL',
extract_mode VARCHAR(32) NOT NULL DEFAULT 'DIRECT',
extract_key_field VARCHAR(64) DEFAULT '',
extract_key_format VARCHAR(64) DEFAULT '',
group_by_fields JSONB DEFAULT '[]'::jsonb,
filter_expression TEXT DEFAULT '',
join_configs JSONB DEFAULT '[]'::jsonb,
field_mappings JSONB DEFAULT '[]'::jsonb,
transform_rules JSONB DEFAULT '[]'::jsonb,
batch_size INT DEFAULT 1000,
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
creator VARCHAR(64) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updater VARCHAR(64) DEFAULT '',
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
CONSTRAINT uk_business_report_extract_code UNIQUE (tenant_id, business_code, report_code, extract_code)
);
COMMENT ON TABLE report_extract_config IS '数据抽取配置表';
COMMENT ON COLUMN report_extract_config.tenant_id IS '租户ID';
COMMENT ON COLUMN report_extract_config.business_code IS '所属业务编码';
COMMENT ON COLUMN report_extract_config.report_code IS '所属报表编码';
COMMENT ON COLUMN report_extract_config.extract_code IS '抽取配置编码';
COMMENT ON COLUMN report_extract_config.extract_name IS '抽取配置名称';
COMMENT ON COLUMN report_extract_config.source_table_name IS '源表表名';
COMMENT ON COLUMN report_extract_config.source_table_alias IS '源表别名';
COMMENT ON COLUMN report_extract_config.target_table_name IS '目标表表名(统计宽表)';
COMMENT ON COLUMN report_extract_config.extract_type IS '抽取类型: FULL全量/INCREMENTAL增量';
COMMENT ON COLUMN report_extract_config.extract_mode IS '抽取模式: DIRECT逐行抽取/AGGREGATE按GROUP BY聚合';
COMMENT ON COLUMN report_extract_config.extract_key_field IS '增量抽取关键字段(如updated_at)';
COMMENT ON COLUMN report_extract_config.extract_key_format IS '关键字段格式(如yyyy-MM-dd HH:mm:ss)';
COMMENT ON COLUMN report_extract_config.group_by_fields IS 'AGGREGATE模式下的GROUP BY字段(JSON数组)';
COMMENT ON COLUMN report_extract_config.filter_expression IS '抽取条件表达式';
COMMENT ON COLUMN report_extract_config.join_configs IS '关联配置(JSON数组)';
COMMENT ON COLUMN report_extract_config.field_mappings IS '字段映射配置(JSON数组)';
COMMENT ON COLUMN report_extract_config.transform_rules IS '转换规则(JSON数组)';
COMMENT ON COLUMN report_extract_config.batch_size IS '批次大小';
CREATE INDEX IF NOT EXISTS idx_extract_business_report ON report_extract_config (business_code, report_code);
-- ----------------------------------------------------------
-- 5. 抽取记录表 (extract_log) - 用于幂等和追踪
-- ----------------------------------------------------------
CREATE TABLE IF NOT EXISTS report_extract_log (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL DEFAULT 0,
business_code VARCHAR(64) NOT NULL,
report_code VARCHAR(64) NOT NULL,
extract_code VARCHAR(64) NOT NULL,
stat_date VARCHAR(16) NOT NULL,
extract_type VARCHAR(32) NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'RUNNING',
total_count INT DEFAULT 0,
success_count INT DEFAULT 0,
fail_count INT DEFAULT 0,
start_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
end_time TIMESTAMP WITH TIME ZONE,
error_message TEXT DEFAULT '',
executor VARCHAR(64) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT uk_extract_keys UNIQUE (tenant_id, business_code, report_code, extract_code, stat_date)
);
COMMENT ON TABLE report_extract_log IS '抽取记录表(幂等追踪)';
COMMENT ON COLUMN report_extract_log.tenant_id IS '租户ID';
COMMENT ON COLUMN report_extract_log.business_code IS '业务编码';
COMMENT ON COLUMN report_extract_log.report_code IS '报表编码';
COMMENT ON COLUMN report_extract_log.extract_code IS '抽取配置编码';
COMMENT ON COLUMN report_extract_log.stat_date IS '统计日期(yyyy-MM-dd)';
COMMENT ON COLUMN report_extract_log.extract_type IS '抽取类型: FULL/INCREMENTAL';
COMMENT ON COLUMN report_extract_log.status IS '状态: RUNNING运行中/SUCCESS成功/FAILED失败';
COMMENT ON COLUMN report_extract_log.total_count IS '总记录数';
COMMENT ON COLUMN report_extract_log.success_count IS '成功记录数';
COMMENT ON COLUMN report_extract_log.fail_count IS '失败记录数';
CREATE INDEX IF NOT EXISTS idx_extract_log_business_report ON report_extract_log (business_code, report_code);
CREATE INDEX IF NOT EXISTS idx_extract_log_stat_date ON report_extract_log (stat_date);
-- ============================================================
-- 字段映射配置结构说明 (field_mappings JSONB)
-- ============================================================
-- [
-- {
-- "source_field": "order_id",
-- "target_field": "order_id",
-- "field_type": "STRING",
-- "default_value": "",
-- "transform_rule": {
-- "type": "DIRECT/MAPPING/CALCULATE",
-- "expression": ""
-- }
-- },
-- {
-- "source_field": "sale_amount",
-- "target_field": "sale_amount_yuan",
-- "field_type": "FLOAT",
-- "default_value": 0,
-- "transform_rule": {
-- "type": "CALCULATE",
-- "expression": "source_value / 100"
-- }
-- }
-- ]
-- ============================================================
-- 转换规则配置结构说明 (transform_rules JSONB)
-- ============================================================
-- [
-- {
-- "rule_code": "status_mapping",
-- "rule_type": "MAPPING",
-- "source_field": "order_status",
-- "target_field": "status_name",
-- "mapping": {
-- "PENDING": "待支付",
-- "PAID": "已支付",
-- "SHIPPED": "已发货",
-- "COMPLETED": "已完成",
-- "REFUNDED": "已退款"
-- }
-- },
-- {
-- "rule_code": "date_format",
-- "rule_type": "FORMAT",
-- "source_field": "create_time",
-- "target_field": "stat_date",
-- "format": "yyyy-MM-dd"
-- }
-- ]
-- ============================================================
-- 关联配置结构说明 (join_configs JSONB)
-- ============================================================
-- [
-- {
-- "join_table": "product_info",
-- "join_alias": "p",
-- "join_type": "LEFT",
-- "join_condition": "s.product_id = p.id",
-- "field_mappings": [
-- {"source_field": "p.category_name", "target_field": "category_name"}
-- ]
-- }
-- ]

229
sql/seed_data_dingtalk.sql Normal file
View File

@@ -0,0 +1,229 @@
-- =============================================
-- 钉钉开放平台初始化数据
--
-- 执行后需配置 tokenOAUTH2 读取 token 列,非 api_key
-- UPDATE api_datasource_platform SET token = '你的oapi access_token'
-- WHERE platform_code = 'dingtalk';
-- =============================================
-- 1. 创建钉钉平台
INSERT INTO api_datasource_platform (
tenant_id, creator, created_at, updater, updated_at,
platform_code, platform_name, description, status,
api_base_url, auth_type,
auth_config,
rate_limit_per_minute, rate_limit_per_hour,
concurrency_limit, request_timeout_ms, max_retries, retry_delay_ms
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
'dingtalk', '钉钉', '钉钉开放平台数据同步', 'ACTIVE',
'https://oapi.dingtalk.com', 'OAUTH2',
'{
"token_in_query": true,
"query_key": "access_token"
}'::jsonb,
60, 3600, 5, 30000, 3, 1000
);
-- 2. 部门列表(递归遍历全量部门树)
-- 先从根(不传 dept_id获取一级部门再对每个子部门递归调用获取下级
-- 请求POSTaccess_token 在 URL 查询参数中
-- 响应:{"errcode":0,"errmsg":"ok","result":[{...}]}
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk'),
'部门列表', 'department_list',
'/topapi/v2/department/listsub', 'POST', 'active', 'inherit',
'{
"parameters_location": "query",
"page_param": "cursor",
"page_size_param": "pageSize",
"language": "zh_CN",
"recursive": {
"key_field": "dept_id",
"target_param": "dept_id"
},
"max_recursive_depth": 20
}'::jsonb,
'{
"success_field": "errcode",
"success_value": 0,
"message_field": "errmsg",
"list_path": "result"
}'::jsonb,
'{
"table_name": "dingtalk_department",
"columns": [
{"name": "dept_id", "type": "BIGINT", "comment": "部门ID"},
{"name": "name", "type": "VARCHAR(300)", "comment": "部门名称"},
{"name": "parent_id", "type": "BIGINT", "comment": "父部门ID"},
{"name": "create_dept_group", "type": "BOOLEAN", "comment": "是否同步创建关联企业群"},
{"name": "auto_add_user", "type": "BOOLEAN", "comment": "新人是否自动加入部门群"}
],
"conflict_keys": ["dept_id"]
}'::jsonb
);
-- 3. 部门用户列表prefetch→department_list游标分页
-- 先递归获取全量部门树,再对每个部门分页拉取用户
-- dept_id 为必填,通过 prefetch 从部门列表注入
-- 响应result.list用户数组result.has_more是否还有更多result.next_cursor下一游标
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk'),
'部门用户列表', 'user_list',
'/topapi/v2/user/list', 'POST', 'active', 'inherit',
'{
"parameters_location": "query",
"page_param": "cursor",
"page_size_param": "size",
"cursor_pagination": true,
"size": 100,
"order_field": "modify_desc",
"language": "zh_CN",
"initial_cursor": 0,
"prefetch": {
"url": "/topapi/v2/department/listsub",
"method": "POST",
"response_path": "result",
"target_param": "dept_id",
"value_field": "dept_id"
}
}'::jsonb,
'{
"success_field": "errcode",
"success_value": 0,
"message_field": "errmsg",
"list_path": "result.list",
"cursor_field": "result.next_cursor",
"has_more_field": "result.has_more"
}'::jsonb,
'{
"table_name": "dingtalk_user",
"columns": [
{"name": "userid", "type": "VARCHAR(100)", "comment": "用户userId"},
{"name": "unionid", "type": "VARCHAR(200)", "comment": "用户唯一标识"},
{"name": "name", "type": "VARCHAR(200)", "comment": "用户姓名"},
{"name": "avatar", "type": "TEXT", "comment": "头像地址"},
{"name": "state_code", "type": "VARCHAR(20)", "comment": "国际电话区号"},
{"name": "mobile", "type": "VARCHAR(50)", "comment": "手机号码"},
{"name": "hide_mobile", "type": "BOOLEAN", "comment": "是否号码隐藏"},
{"name": "telephone", "type": "VARCHAR(50)", "comment": "分机号"},
{"name": "job_number", "type": "VARCHAR(100)", "comment": "员工工号"},
{"name": "title", "type": "VARCHAR(200)", "comment": "职位"},
{"name": "email", "type": "VARCHAR(200)", "comment": "员工邮箱"},
{"name": "org_email", "type": "VARCHAR(200)", "comment": "企业邮箱"},
{"name": "work_place", "type": "VARCHAR(300)", "comment": "办公地点"},
{"name": "remark", "type": "TEXT", "comment": "备注"},
{"name": "dept_id_list", "type": "JSONB", "comment": "所属部门id列表"},
{"name": "dept_order", "type": "INT", "comment": "员工在部门中的排序"},
{"name": "extension", "type": "TEXT", "comment": "扩展属性"},
{"name": "hired_date", "type": "BIGINT", "comment": "入职时间"},
{"name": "active", "type": "BOOLEAN", "comment": "是否激活钉钉"},
{"name": "admin", "type": "BOOLEAN", "comment": "是否企业管理员"},
{"name": "boss", "type": "BOOLEAN", "comment": "是否企业老板"},
{"name": "leader", "type": "BOOLEAN", "comment": "是否部门主管"},
{"name": "exclusive_account", "type": "BOOLEAN", "comment": "是否企业账号"}
],
"conflict_keys": ["userid"]
}'::jsonb
);
-- 4. 考勤数据查询单个用户单日prefetch→user_list
-- 需先同步 user_list 获取全量用户,再对每个用户调用此接口查询考勤数据
-- userid 通过 prefetch 从 user_list 注入work_date 固定为当天日期
-- 响应result 对象(包含 attendance_result_list/check_record_list/approve_list 等)
-- 注意:当前代码支持两级 prefetch 链(即本接口 prefetch→user_list
-- user_list 自有 prefetch→department_list但 user_list 的 dept_id 依赖
-- 在作为 prefetch 来源时不会自动解析。若需全量同步所有用户的考勤数据,
-- 建议先手动同步 user_list 和 department_list再同步此接口。
-- 使用前请将 work_date 更新为目标日期,如 '2026-06-03'
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk'),
'考勤数据查询', 'attendance_getupdatedata',
'/topapi/attendance/getupdatedata', 'POST', 'active', 'inherit',
'{
"parameters_location": "query",
"prefetch": {
"url": "/topapi/v2/user/list",
"method": "POST",
"response_path": "result.list",
"target_param": "userid",
"value_field": "userid"
},
"work_date": "2026-06-03"
}'::jsonb,
'{
"success_field": "errcode",
"success_value": 0,
"message_field": "errmsg",
"list_path": "result",
"single_record": true
}'::jsonb,
'{
"table_name": "dingtalk_attendance",
"columns": [
{"name": "userid", "type": "VARCHAR(100)", "comment": "用户userId"},
{"name": "work_date", "type": "VARCHAR(30)", "comment": "查询日期"},
{"name": "corpId", "type": "VARCHAR(100)", "comment": "企业corpId"},
{"name": "attendance_result_list", "type": "JSONB", "comment": "打卡结果列表"},
{"name": "check_record_list", "type": "JSONB", "comment": "打卡详情列表"},
{"name": "approve_list", "type": "JSONB", "comment": "审批单列表"},
{"name": "rest_time_vo_list", "type": "JSONB", "comment": "班次内休息信息"},
{"name": "rest_end_time", "type": "BIGINT", "comment": "休息结束时间"},
{"name": "rest_begin_time", "type": "BIGINT", "comment": "休息开始时间"}
],
"conflict_keys": ["userid", "work_date"]
}'::jsonb
);
-- 5. 角色列表偏移量分页offset/size + hasMore
-- 响应result.list角色组数组result.hasMore是否还有更多
-- 每个角色组内包含 roles 数组({id, name})你
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk'),
'角色列表', 'role_list',
'/topapi/role/list', 'POST', 'active', 'inherit',
'{
"parameters_location": "query",
"page_param": "offset",
"page_size_param": "size",
"size": 200,
"offset": 0,
"pagination_mode": "offset"
}'::jsonb,
'{
"success_field": "errcode",
"success_value": 0,
"message_field": "errmsg",
"list_path": "result.list",
"has_more_field": "result.has_more"
}'::jsonb,
'{
"table_name": "dingtalk_role",
"columns": [
{"name": "groupId", "type": "BIGINT", "comment": "角色组ID"},
{"name": "name", "type": "VARCHAR(200)", "comment": "角色组名称"},
{"name": "roles", "type": "JSONB", "comment": "角色列表"}
],
"conflict_keys": ["groupId"]
}'::jsonb
);

View File

@@ -0,0 +1,69 @@
-- =============================================
-- 钉钉智能人事平台初始化数据
-- 注意:此平台使用 x-acs-dingtalk-access-token Header 认证
-- API 基础地址为 https://api.dingtalk.com与 oapi 不同)
--
-- 执行后需配置 tokenOAUTH2 读取 token 列,非 api_key
-- UPDATE api_datasource_platform SET token = '你的hrm access_token'
-- WHERE platform_code = 'dingtalk_hrm';
-- =============================================
-- 1. 创建钉钉智能人事平台
INSERT INTO api_datasource_platform (
tenant_id, creator, created_at, updater, updated_at,
platform_code, platform_name, description, status,
api_base_url, auth_type,
auth_config,
rate_limit_per_minute, rate_limit_per_hour,
concurrency_limit, request_timeout_ms, max_retries, retry_delay_ms
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
'dingtalk_hrm', '钉钉智能人事', '钉钉智能人事数据同步header 认证)', 'ACTIVE',
'https://api.dingtalk.com', 'OAUTH2',
'{
"token_in_query": false,
"header_name": "x-acs-dingtalk-access-token",
"header_format": "{token}"
}'::jsonb,
60, 3600, 5, 30000, 3, 1000
);
-- 2. 企业职位列表游标分页hasMore 判结束)
-- 响应list职位数组nextToken游标hasMore是否还有更多
-- 注意:此接口成功时无 errcode 字段parseRespExt 在找不到 success_field 时自动跳过检查
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk_hrm'),
'企业职位列表', 'position_list',
'/v1.0/hrm/positions/query', 'POST', 'active', 'inherit',
'{
"cursor_pagination": true,
"page_param": "nextToken",
"page_size_param": "maxResults",
"pageSize": 200,
"initial_cursor": 0,
"parameters_location": "query"
}'::jsonb,
'{
"list_path": "list",
"cursor_field": "nextToken",
"has_more_field": "hasMore"
}'::jsonb,
'{
"table_name": "dingtalk_position",
"columns": [
{"name": "positionId", "type": "VARCHAR(100)", "comment": "职位ID"},
{"name": "positionName", "type": "VARCHAR(300)", "comment": "职位名称"},
{"name": "positionCategoryId", "type": "VARCHAR(100)", "comment": "职位类别ID"},
{"name": "jobId", "type": "VARCHAR(100)", "comment": "所属职务ID"},
{"name": "positionDes", "type": "TEXT", "comment": "职位描述"},
{"name": "rankIdList", "type": "JSONB", "comment": "职级ID列表"},
{"name": "status", "type": "INT", "comment": "职位状态 0启用 1停用"}
],
"conflict_keys": ["positionId"]
}'::jsonb
);

View File

@@ -0,0 +1,175 @@
-- =============================================
-- 钉钉智能薪酬平台初始化数据
--
-- 认证方式app-id + signature 头部
-- 签名算法MD5(request_body_string + app_secret).toUpperCase()
--
-- 执行后需在 auth_config 中配置 app_id 和 app_secret
-- UPDATE api_datasource_platform SET auth_config = jsonb_set(
-- jsonb_set(auth_config, '{app_id}', '"你的app-id"'),
-- '{app_secret}', '"你的app-secret"'
-- ) WHERE platform_code = 'dingtalk_salary';
-- =============================================
-- 1. 创建钉钉智能薪酬平台
INSERT INTO api_datasource_platform (
tenant_id, creator, created_at, updater, updated_at,
platform_code, platform_name, description, status,
api_base_url, auth_type,
auth_config,
rate_limit_per_minute, rate_limit_per_hour,
concurrency_limit, request_timeout_ms, max_retries, retry_delay_ms
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
'dingtalk_salary', '钉钉智能薪酬', '钉钉智能薪酬数据同步app-id + signature 头部认证)', 'ACTIVE',
'https://salary.eapps.dingtalkcloud.com', 'APP_SIGNATURE',
'{
"app_id": "",
"app_secret": "",
"sign_algorithm": "md5_upper_body",
"app_id_header": "app-id",
"sign_header": "signature"
}'::jsonb,
60, 3600, 3, 30000, 3, 1000
);
-- 2. 部门列表(无分页,单次请求返回全部部门)
-- 无请求入参,直接 POST 即可
-- 响应:{"code":"200","success":true,"data":[{"name":"研发部","value":"93639012","ext":"-1"},...]}
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk_salary'),
'公司部门列表', 'salary_dept_list',
'/oapi/salary/dept/list', 'POST', 'active', 'inherit',
'{}'::jsonb,
'{
"success_field": "code",
"success_value": 200,
"message_field": "msg",
"list_path": "data"
}'::jsonb,
'{
"table_name": "dingtalk_salary_dept",
"columns": [
{"name": "name", "type": "VARCHAR(300)", "comment": "部门名称"},
{"name": "value", "type": "VARCHAR(100)", "comment": "部门ID"},
{"name": "ext", "type": "VARCHAR(100)", "comment": "父部门ID-1为根部门"}
],
"conflict_keys": ["value"]
}'::jsonb
);
-- 3. 按部门导出当月薪资报表prefetch→salary_dept_list
-- 先通过 dept/list 获取全量部门列表,再对每个部门调用此接口
-- deptId 通过 prefetch 注入statisticsMonth 通过 row_inject 注入到每行
-- 使用前请将 statisticsMonth 更新为目标月份,如 "2026-06"
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk_salary'),
'按部门薪资报表', 'salary_statistics',
'/oapi/salary/statistics/dept', 'POST', 'active', 'inherit',
'{
"statisticsMonth": "2026-06",
"row_inject": ["statisticsMonth"],
"prefetch": {
"url": "/oapi/salary/dept/list",
"method": "POST",
"response_path": "data",
"target_param": "deptId",
"value_field": "value"
}
}'::jsonb,
'{
"success_field": "code",
"success_value": 200,
"message_field": "msg",
"list_path": "data"
}'::jsonb,
'{
"table_name": "dingtalk_salary_statistics",
"columns": [
{"name": "deptId", "type": "BIGINT", "comment": "部门ID"},
{"name": "statisticsMonth", "type": "VARCHAR(7)", "comment": "薪资月(yyyy-MM)"},
{"name": "name", "type": "VARCHAR(200)", "comment": "报表项名称"},
{"name": "value", "type": "VARCHAR(100)", "comment": "报表项数据"}
],
"conflict_keys": ["deptId", "statisticsMonth", "name"]
}'::jsonb
);
-- 4. 人力成本报表(无分页,单次请求返回指定月份的人力成本汇总)
-- calBizId 为空时默认为当前月份,格式为 yyyyMM + "M",如 "202606M"
-- 使用前可将 calBizId 更新为目标月份
-- 响应data.sumStatisticsData 包含各成本项itemId/itemName/itemDesc/sValue/value
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk_salary'),
'人力成本报表', 'salary_statistic_report',
'/oapi/salary/statistic/report/data', 'POST', 'active', 'inherit',
'{
"calBizId": "202606M"
}'::jsonb,
'{
"success_field": "code",
"success_value": 200,
"message_field": "msg",
"list_path": "data",
"single_record": true
}'::jsonb,
'{
"table_name": "dingtalk_salary_statistic_report",
"columns": [
{"name": "calBizId", "type": "VARCHAR(20)", "comment": "薪资月份"},
{"name": "sumStatisticsData", "type": "JSONB", "comment": "人力成本报表数据"}
],
"conflict_keys": ["calBizId"]
}'::jsonb
);
-- 5. 按薪资组获取人力成本报表(无分页,单次请求返回指定薪资组的人力成本汇总)
-- salaryGroupName 为必填,使用前需更新为实际的薪资组名称
-- calBizId 为空时默认为当前月份,格式为 yyyyMM + "M"
-- row_inject 会将请求中的 salaryGroupName 注入到每行,便于区分不同薪资组的报表
INSERT INTO api_interface (
tenant_id, creator, created_at, updater, updated_at,
platform_id, name, code, url, method, status, auth_type,
request_config, response_config, table_definition
) VALUES (
1, 'admin', NOW(), 'admin', NOW(),
(SELECT id FROM api_datasource_platform WHERE platform_code = 'dingtalk_salary'),
'按薪资组人力成本报表', 'salary_statistic_report_group',
'/oapi/salary/statistic/report/groupData', 'POST', 'active', 'inherit',
'{
"calBizId": "202606M",
"salaryGroupName": "",
"row_inject": ["salaryGroupName"]
}'::jsonb,
'{
"success_field": "code",
"success_value": 200,
"message_field": "msg",
"list_path": "data",
"single_record": true
}'::jsonb,
'{
"table_name": "dingtalk_salary_statistic_report_group",
"columns": [
{"name": "calBizId", "type": "VARCHAR(20)", "comment": "薪资月份"},
{"name": "salaryGroupName", "type": "VARCHAR(200)", "comment": "薪资组名称"},
{"name": "sumStatisticsData", "type": "JSONB", "comment": "人力成本报表数据"}0
],
"conflict_keys": ["calBizId", "salaryGroupName"]
}'::jsonb
);

View File

@@ -0,0 +1,435 @@
-- ============================================================
-- 快手电商 - 报表系统初始化数据
-- 基于 seed_data_kuaishou.sql 中实际表结构生成
-- 覆盖报表: 订单 / 商品 / 售后 / 分销订单 / 代发订单
-- ============================================================
-- =============================================
-- 1. 业务配置 (report_business_config)
-- =============================================
INSERT INTO report_business_config (tenant_id, business_code, business_name, description, status, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', '快手电商', '快手电商平台订单、商品、售后、分销数据分析', 'ACTIVE',
'{"platform":"kuaishou","timezone":"Asia/Shanghai"}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code) DO NOTHING;
-- =============================================
-- 2. 报表配置 (report_report_config)
-- =============================================
-- 2.1 订单分析
INSERT INTO report_report_config (tenant_id, business_code, report_code, report_name, description, status, stat_table_name, stat_table_comment, date_field, primary_keys, conflict_keys, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'order_analysis', '订单分析', '基于 kuaishou_order_list 的订单维度聚合分析,支持按日期/状态/地区/支付方式/渠道等维度', 'ACTIVE',
'kuaishou_order_stat', '快手订单统计宽表(聚合自 kuaishou_order_list',
'stat_date',
'["id"]'::jsonb,
'["stat_date","oid"]'::jsonb,
'{"defaultTimeRange":"last_30_days","defaultDimensions":["stat_date"],"defaultIndicators":[{"field":"order_count","aggregate":"COUNT"},{"field":"total_fee","aggregate":"SUM"}]}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code) DO NOTHING;
-- 2.2 商品分析
INSERT INTO report_report_config (tenant_id, business_code, report_code, report_name, description, status, stat_table_name, stat_table_comment, date_field, primary_keys, conflict_keys, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'item_analysis', '商品分析', '基于 kuaishou_item_list 的商品维度销量、销售额分析,支持按类目/类型/上下架状态等维度', 'ACTIVE',
'kuaishou_item_stat', '快手商品统计宽表(聚合自 kuaishou_item_list',
'stat_date',
'["id"]'::jsonb,
'["stat_date","kwai_item_id","category_id"]'::jsonb,
'{"defaultTimeRange":"last_30_days","defaultDimensions":["stat_date","category_name"],"defaultIndicators":[{"field":"sales_volume","aggregate":"SUM"},{"field":"sales_amount","aggregate":"SUM"}]}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code) DO NOTHING;
-- 2.3 售后分析
INSERT INTO report_report_config (tenant_id, business_code, report_code, report_name, description, status, stat_table_name, stat_table_comment, date_field, primary_keys, conflict_keys, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'refund_analysis', '售后分析', '基于 kuaishou_refund_list 的售后维度分析,退款金额/退款率等核心指标', 'ACTIVE',
'kuaishou_refund_stat', '快手售后统计宽表(聚合自 kuaishou_refund_list',
'stat_date',
'["id"]'::jsonb,
'["stat_date","refund_id"]'::jsonb,
'{"defaultTimeRange":"last_30_days","defaultDimensions":["stat_date","refund_type"],"defaultIndicators":[{"field":"refund_count","aggregate":"COUNT"},{"field":"refund_fee","aggregate":"SUM"}]}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code) DO NOTHING;
-- 2.4 分销订单分析
INSERT INTO report_report_config (tenant_id, business_code, report_code, report_name, description, status, stat_table_name, stat_table_comment, date_field, primary_keys, conflict_keys, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'cps_order_analysis', '分销订单分析', '基于 kuaishou_cps_order_list 的分销订单维度分析,含分销收入/佣金等指标', 'ACTIVE',
'kuaishou_cps_order_stat', '快手分销订单统计宽表(聚合自 kuaishou_cps_order_list',
'stat_date',
'["id"]'::jsonb,
'["stat_date","oid"]'::jsonb,
'{"defaultTimeRange":"last_30_days","defaultDimensions":["stat_date","status"],"defaultIndicators":[{"field":"order_count","aggregate":"COUNT"},{"field":"estimated_income","aggregate":"SUM"}]}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code) DO NOTHING;
-- 2.5 代发订单分析
INSERT INTO report_report_config (tenant_id, business_code, report_code, report_name, description, status, stat_table_name, stat_table_comment, date_field, primary_keys, conflict_keys, config, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', '代发订单分析', '基于 kuaishou_dropshipping_order_list 的代发订单维度分析,按厂家/物流/地区等维度', 'ACTIVE',
'kuaishou_dropshipping_stat', '快手代发订单统计宽表(聚合自 kuaishou_dropshipping_order_list',
'stat_date',
'["id"]'::jsonb,
'["stat_date","dropshipping_order_code"]'::jsonb,
'{"defaultTimeRange":"last_30_days","defaultDimensions":["stat_date","dropshipping_status"],"defaultIndicators":[{"field":"order_count","aggregate":"COUNT"}]}'::jsonb,
'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code) DO NOTHING;
-- =============================================
-- 3. 字段配置 (report_field_config)
-- =============================================
-- ----------------------------------------------------------
-- 3.1 订单分析 - 字段配置
-- 源表: kuaishou_order_list
-- 实际列: oid, status, createTime, updateTime, payTime, sendTime, recvTime,
-- refundTime, totalFee, expressFee, discountFee, originalPrice,
-- buyerOpenId, sellerOpenId, buyerNick, sellerNick, remark, itemTitle,
-- num, price, activityType, cpsType, payType, payChannel, channel,
-- commentStatus, priorityDelivery, carrierType, carrierId,
-- province, city, district, provinceCode, cityCode, districtCode
-- ----------------------------------------------------------
-- 维度字段
INSERT INTO report_field_config (tenant_id, business_code, report_code, field_code, field_name, field_type, data_type, field_role, is_aggregatable, is_filterable, is_queryable, is_sortable, default_aggregate, valid_aggregates, filter_operators, expression, expression_type, format_pattern, unit, dict_code, sort_order, group_name, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'order_analysis', 'stat_date', '统计日期', 'DATE', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', '', 'yyyy-MM-dd', '', '', 1, '时间维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'oid', '订单ID', 'BIGINT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 2, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'status', '订单状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'order_status_dict', 3, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'province', '省份', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 4, '地域维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'city', '城市', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 5, '地域维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'district', '区县', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 6, '地域维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'pay_type', '支付类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'pay_type_dict', 7, '支付维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'pay_channel', '支付渠道', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 8, '支付维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'channel', '分销渠道', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 9, '渠道维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'activity_type', '活动类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 10, '活动维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'buyer_nick', '买家昵称', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE"]'::jsonb, '', '', '', '', '', 11, '用户维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'item_title', '商品标题', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE"]'::jsonb, '', '', '', '', '', 12, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
-- 指标字段
(1, 'kuaishou_ecommerce', 'order_analysis', 'order_count', '订单数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT","SUM"]'::jsonb, '[]'::jsonb, '1', 'CALCULATED', '#,##0', '', '', 21, '订单指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'total_fee', '订单金额(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', 'ORIGINAL', '', '', '', 22, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'total_fee_yuan', '订单金额(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, 'total_fee / 100.0', 'CALCULATED', '#,##0.00', '', '', 23, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'express_fee', '运费(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 24, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'express_fee_yuan', '运费(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, 'express_fee / 100.0', 'CALCULATED', '#,##0.00', '', '', 25, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'discount_fee', '优惠金额(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 26, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'discount_fee_yuan', '优惠金额(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, 'discount_fee / 100.0', 'CALCULATED', '#,##0.00', '', '', 27, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'original_price', '原价(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 28, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'item_num', '商品件数', 'INT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '#,##0', '', '', 29, '商品指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'avg_order_amount', '客单价(元)', 'FLOAT', 'STRING', 'INDICATOR', true, false, true, true, 'AVG', '["AVG"]'::jsonb, '[]'::jsonb, 'total_fee / 100.0 / NULLIF(order_count, 0)', 'CALCULATED', '#,##0.00', '', '', 30, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'order_analysis', 'discount_rate', '优惠率(%)', 'FLOAT', 'STRING', 'INDICATOR', true, false, true, true, 'AVG', '["AVG"]'::jsonb, '[]'::jsonb, 'CASE WHEN SUM(total_fee) > 0 THEN SUM(discount_fee) * 100.0 / (SUM(total_fee) + SUM(discount_fee)) ELSE 0 END', 'CALCULATED', '#,##0.00', '%', '', 31, '比率指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, field_code) DO NOTHING;
-- ----------------------------------------------------------
-- 3.2 商品分析 - 字段配置
-- 源表: kuaishou_item_list
-- 实际列: kwaiItemId, relItemId, title, details, categoryId, categoryName,
-- price, volume, status, auditStatus, auditReason, shelfStatus,
-- itemType, createTime, updateTime, expressTemplateId, linkUrl
-- ----------------------------------------------------------
-- 维度字段
INSERT INTO report_field_config (tenant_id, business_code, report_code, field_code, field_name, field_type, data_type, field_role, is_aggregatable, is_filterable, is_queryable, is_sortable, default_aggregate, valid_aggregates, filter_operators, expression, expression_type, format_pattern, unit, dict_code, sort_order, group_name, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'item_analysis', 'stat_date', '统计日期', 'DATE', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', '', 'yyyy-MM-dd', '', '', 1, '时间维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'kwai_item_id', '商品ID', 'BIGINT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 2, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'title', '商品标题', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE","IN"]'::jsonb, '', '', '', '', '', 3, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'category_id', '类目ID', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 4, '类目维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'category_name', '类目名称', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 5, '类目维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'item_type', '商品类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'item_type_dict', 6, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'shelf_status', '上下架状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'shelf_status_dict', 7, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'audit_status', '审核状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 8, '商品维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
-- 指标字段
(1, 'kuaishou_ecommerce', 'item_analysis', 'sales_volume', '销量', 'INT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', 'ORIGINAL', '#,##0', '', '', 21, '销售指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'price', '商品价格(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'AVG', '["AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 22, '价格指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'price_yuan', '商品价格(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'AVG', '["AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, 'price / 100.0', 'CALCULATED', '#,##0.00', '', '', 23, '价格指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'sales_amount', '销售额(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 24, '销售指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'sales_amount_yuan', '销售额(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, 'sales_amount / 100.0', 'CALCULATED', '#,##0.00', '', '', 25, '销售指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'item_count', '商品数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT"]'::jsonb, '[]'::jsonb, 'COUNT(DISTINCT kwai_item_id)', 'CALCULATED', '#,##0', '', '', 26, '商品指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'item_analysis', 'avg_price_per_unit', '件均价(元)', 'FLOAT', 'STRING', 'INDICATOR', true, false, true, true, 'AVG', '["AVG"]'::jsonb, '[]'::jsonb, 'SUM(sales_amount) / 100.0 / NULLIF(SUM(sales_volume), 0)', 'CALCULATED', '#,##0.00', '', '', 27, '价格指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, field_code) DO NOTHING;
-- ----------------------------------------------------------
-- 3.3 售后分析 - 字段配置
-- 源表: kuaishou_refund_list
-- 实际列: refundId, oid, itemId, skuId, relSkuId, skuNick, handlingWay,
-- negotiateStatus, refundFee, refundReason, refundReasonDesc,
-- refundDesc, refundType, status, receiptStatus, buyerId, sellerId,
-- logisticsId, relItemId, submitTime, createTime, updateTime,
-- negotiateUpdateTime, endTime, expireTime
-- ----------------------------------------------------------
-- 维度字段
INSERT INTO report_field_config (tenant_id, business_code, report_code, field_code, field_name, field_type, data_type, field_role, is_aggregatable, is_filterable, is_queryable, is_sortable, default_aggregate, valid_aggregates, filter_operators, expression, expression_type, format_pattern, unit, dict_code, sort_order, group_name, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'refund_analysis', 'stat_date', '统计日期', 'DATE', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', '', 'yyyy-MM-dd', '', '', 1, '时间维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_id', '售后单ID', 'BIGINT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 2, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_type', '售后类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'refund_type_dict', 3, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_reason_desc', '售后原因', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 4, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'status', '售后状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'refund_status_dict', 5, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'handling_way', '处理方式', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 6, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'negotiate_status', '协商状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 7, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
-- 指标字段
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_count', '售后单数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT","SUM"]'::jsonb, '[]'::jsonb, '1', 'CALCULATED', '#,##0', '', '', 21, '售后指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_fee', '退款金额(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 22, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_fee_yuan', '退款金额(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, 'refund_fee / 100.0', 'CALCULATED', '#,##0.00', '', '', 23, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'avg_refund_amount', '笔均退款(元)', 'FLOAT', 'STRING', 'INDICATOR', true, false, true, true, 'AVG', '["AVG"]'::jsonb, '[]'::jsonb, 'SUM(refund_fee) / 100.0 / NULLIF(SUM(refund_count), 0)', 'CALCULATED', '#,##0.00', '', '', 24, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'refund_analysis', 'negotiate_count', '协商中数量', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'SUM', '["SUM"]'::jsonb, '[]'::jsonb, 'CASE WHEN negotiate_status = 1 THEN 1 ELSE 0 END', 'CALCULATED', '#,##0', '', '', 25, '售后指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, field_code) DO NOTHING;
-- ----------------------------------------------------------
-- 3.4 分销订单分析 - 字段配置
-- 源表: kuaishou_cps_order_list
-- 实际列: oid, distributorId, distributorName, sellerId, status,
-- settlementTime, settlementSuccessTime, refundTime, payTime,
-- expressFee, totalFee, commissionRate, estimatedIncome,
-- createTime, updateTime, platformDpRate, activityUserId,
-- activityUserNickname, investmentPromotionRate,
-- investmentPromotionAmount, buyerOpenId, settlementBizType,
-- promoterServiceInCome, promoterExcitationInCome,
-- investmentServiceInCome, investmentExcitationInCome,
-- orderChannel, activityId, itemId
-- ----------------------------------------------------------
-- 维度字段
INSERT INTO report_field_config (tenant_id, business_code, report_code, field_code, field_name, field_type, data_type, field_role, is_aggregatable, is_filterable, is_queryable, is_sortable, default_aggregate, valid_aggregates, filter_operators, expression, expression_type, format_pattern, unit, dict_code, sort_order, group_name, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'stat_date', '统计日期', 'DATE', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', '', 'yyyy-MM-dd', '', '', 1, '时间维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'oid', '订单ID', 'BIGINT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 2, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'status', '分销单状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'cps_status_dict', 3, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'distributor_name', '分销者', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE"]'::jsonb, '', '', '', '', '', 4, '分销维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'order_channel', '出单渠道', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 5, '渠道维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'settlement_biz_type', '业务类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 6, '业务维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
-- 指标字段
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'order_count', '订单数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT","SUM"]'::jsonb, '[]'::jsonb, '1', 'CALCULATED', '#,##0', '', '', 21, '订单指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'total_fee', '实付金额(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 22, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'total_fee_yuan', '实付金额(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, 'total_fee / 100.0', 'CALCULATED', '#,##0.00', '', '', 23, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'express_fee', '运费(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 24, '金额指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'estimated_income', '分销预估收入(分)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX"]'::jsonb, '["=",">=","<="]'::jsonb, '', 'ORIGINAL', '', '', '', 25, '收入指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'estimated_income_yuan', '分销预估收入(元)', 'FLOAT', 'STRING', 'INDICATOR', true, true, true, true, 'SUM', '["SUM","AVG","MAX"]'::jsonb, '["=",">=","<="]'::jsonb, 'estimated_income / 100.0', 'CALCULATED', '#,##0.00', '', '', 26, '收入指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'commission_rate', '分销佣金率(%)', 'BIGINT', 'STRING', 'INDICATOR', true, true, true, true, 'AVG', '["AVG","MAX","MIN"]'::jsonb, '["=",">=","<="]'::jsonb, 'commission_rate / 10.0', 'CALCULATED', '#,##0.0', '%', '', 27, '佣金指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, field_code) DO NOTHING;
-- ----------------------------------------------------------
-- 3.5 代发订单分析 - 字段配置
-- 源表: kuaishou_dropshipping_order_list
-- 实际列: oid, dropshippingOrderCode, payTime, buyerOpenId, buyerNick,
-- sellerOpenId, sellerNick, orderStatus, orderStatusDesc,
-- refundStatus, refundStatusDesc, orderType, orderTypeDesc,
-- deliveryTime, createTime, updateTime, waybillCode,
-- expressCompanyCode, expressCompanyName, factoryCode, factoryName,
-- allocateTime, dropshippingStatus, dropshippingStatusDesc,
-- cancelAllocateTime, cancelAllocateReason, name, mobile,
-- provinceName, cityName, districtName, detailAddress
-- ----------------------------------------------------------
-- 维度字段
INSERT INTO report_field_config (tenant_id, business_code, report_code, field_code, field_name, field_type, data_type, field_role, is_aggregatable, is_filterable, is_queryable, is_sortable, default_aggregate, valid_aggregates, filter_operators, expression, expression_type, format_pattern, unit, dict_code, sort_order, group_name, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'stat_date', '统计日期', 'DATE', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=",">=","<=","BETWEEN"]'::jsonb, '', '', 'yyyy-MM-dd', '', '', 1, '时间维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'dropshipping_order_code', '代发订单编码', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 2, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'order_status', '订单状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', 'dropshipping_status_dict', 3, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'dropshipping_status', '代发状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 4, '代发维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'factory_name', '代发厂家', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE"]'::jsonb, '', '', '', '', '', 5, '厂家维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'express_company_name', '物流公司', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","LIKE"]'::jsonb, '', '', '', '', '', 6, '物流维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'province_name', '省份', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 7, '地域维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'city_name', '城市', 'VARCHAR', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN","LIKE"]'::jsonb, '', '', '', '', '', 8, '地域维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'order_type', '订单类型', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 9, '订单维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'refund_status', '售后状态', 'INT', 'STRING', 'DIMENSION', false, true, true, true, '', '[]'::jsonb, '["=","IN"]'::jsonb, '', '', '', '', '', 10, '售后维度', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
-- 指标字段
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'order_count', '订单数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT","SUM"]'::jsonb, '[]'::jsonb, '1', 'CALCULATED', '#,##0', '', '', 21, '订单指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'factory_count', '厂家数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'COUNT', '["COUNT"]'::jsonb, '[]'::jsonb, 'COUNT(DISTINCT factory_code)', 'CALCULATED', '#,##0', '', '', 22, '厂家指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW()),
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'pending_allocate_count', '待分配数', 'INT', 'STRING', 'INDICATOR', true, false, true, true, 'SUM', '["SUM"]'::jsonb, '[]'::jsonb, 'CASE WHEN dropshipping_status = 1 THEN 1 ELSE 0 END', 'CALCULATED', '#,##0', '', '', 23, '订单指标', 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, field_code) DO NOTHING;
-- =============================================
-- 4. 抽取配置 (report_extract_config)
-- =============================================
-- ----------------------------------------------------------
-- 4.1 订单分析 - AGGREGATE 聚合抽取
-- 源: kuaishou_order_list → 目标: kuaishou_order_stat
-- 按 createTime 转 stat_dateGROUP BY 维度字段,聚合指标
-- ----------------------------------------------------------
INSERT INTO report_extract_config (tenant_id, business_code, report_code, extract_code, extract_name, source_table_name, source_table_alias, target_table_name, is_enabled, extract_type, extract_mode, extract_key_field, extract_key_format, group_by_fields, filter_expression, join_configs, field_mappings, transform_rules, batch_size, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'order_analysis', 'order_daily_stat', '订单每日统计抽取',
'kuaishou_order_list', 'o',
'kuaishou_order_stat', true, 'INCREMENTAL', 'AGGREGATE',
'updateTime', 'yyyy-MM-dd',
'["stat_date","oid","status","province","city","district","pay_type","pay_channel","channel","activity_type","buyer_nick","item_title"]'::jsonb,
'',
'[]'::jsonb,
'[
{"sourceField":"stat_date","targetField":"stat_date","fieldType":"DATE"},
{"sourceField":"oid","targetField":"oid","fieldType":"BIGINT","defaultValue":0},
{"sourceField":"status","targetField":"status","fieldType":"INT","defaultValue":0},
{"sourceField":"province","targetField":"province","fieldType":"VARCHAR"},
{"sourceField":"city","targetField":"city","fieldType":"VARCHAR"},
{"sourceField":"district","targetField":"district","fieldType":"VARCHAR"},
{"sourceField":"payType","targetField":"pay_type","fieldType":"INT","defaultValue":0},
{"sourceField":"payChannel","targetField":"pay_channel","fieldType":"VARCHAR"},
{"sourceField":"channel","targetField":"channel","fieldType":"VARCHAR"},
{"sourceField":"activityType","targetField":"activity_type","fieldType":"INT","defaultValue":0},
{"sourceField":"buyerNick","targetField":"buyer_nick","fieldType":"VARCHAR"},
{"sourceField":"itemTitle","targetField":"item_title","fieldType":"VARCHAR"},
{"sourceField":"oid","targetField":"order_count","fieldType":"INT","aggregateFunction":"COUNT","defaultValue":0},
{"sourceField":"totalFee","targetField":"total_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"expressFee","targetField":"express_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"discountFee","targetField":"discount_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"originalPrice","targetField":"original_price","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"num","targetField":"item_num","fieldType":"INT","aggregateFunction":"SUM","defaultValue":0}
]'::jsonb,
'[
{"ruleCode":"ts_to_date","ruleType":"FORMAT","expression":"","format":"yyyy-MM-dd","sourceField":"createTime","targetField":"stat_date"}
]'::jsonb,
500, 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, extract_code) DO NOTHING;
-- ----------------------------------------------------------
-- 4.2 商品分析 - AGGREGATE 聚合抽取
-- 源: kuaishou_item_list → 目标: kuaishou_item_stat
-- ----------------------------------------------------------
INSERT INTO report_extract_config (tenant_id, business_code, report_code, extract_code, extract_name, source_table_name, source_table_alias, target_table_name, is_enabled, extract_type, extract_mode, extract_key_field, extract_key_format, group_by_fields, filter_expression, join_configs, field_mappings, transform_rules, batch_size, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'item_analysis', 'item_daily_stat', '商品每日统计抽取',
'kuaishou_item_list', 'i',
'kuaishou_item_stat', true, 'INCREMENTAL', 'AGGREGATE',
'updateTime', 'yyyy-MM-dd',
'["stat_date","kwai_item_id","title","category_id","category_name","item_type","shelf_status","audit_status"]'::jsonb,
'',
'[]'::jsonb,
'[
{"sourceField":"stat_date","targetField":"stat_date","fieldType":"DATE"},
{"sourceField":"kwaiItemId","targetField":"kwai_item_id","fieldType":"BIGINT","defaultValue":0},
{"sourceField":"title","targetField":"title","fieldType":"VARCHAR"},
{"sourceField":"categoryId","targetField":"category_id","fieldType":"INT","defaultValue":0},
{"sourceField":"categoryName","targetField":"category_name","fieldType":"VARCHAR"},
{"sourceField":"itemType","targetField":"item_type","fieldType":"INT","defaultValue":0},
{"sourceField":"shelfStatus","targetField":"shelf_status","fieldType":"INT","defaultValue":0},
{"sourceField":"auditStatus","targetField":"audit_status","fieldType":"INT","defaultValue":0},
{"sourceField":"volume","targetField":"sales_volume","fieldType":"INT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"price","targetField":"price","fieldType":"BIGINT","aggregateFunction":"AVG","defaultValue":0},
{"sourceField":"kwaiItemId","targetField":"sales_amount","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0,
"transformRule":{"ruleCode":"volume_times_price","ruleType":"CALCULATE","expression":"volume * price"}}
]'::jsonb,
'[
{"ruleCode":"ts_to_date","ruleType":"FORMAT","expression":"","format":"yyyy-MM-dd","sourceField":"createTime","targetField":"stat_date"}
]'::jsonb,
500, 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, extract_code) DO NOTHING;
-- ----------------------------------------------------------
-- 4.3 售后分析 - AGGREGATE 聚合抽取
-- 源: kuaishou_refund_list → 目标: kuaishou_refund_stat
-- ----------------------------------------------------------
INSERT INTO report_extract_config (tenant_id, business_code, report_code, extract_code, extract_name, source_table_name, source_table_alias, target_table_name, is_enabled, extract_type, extract_mode, extract_key_field, extract_key_format, group_by_fields, filter_expression, join_configs, field_mappings, transform_rules, batch_size, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'refund_analysis', 'refund_daily_stat', '售后每日统计抽取',
'kuaishou_refund_list', 'r',
'kuaishou_refund_stat', true, 'INCREMENTAL', 'AGGREGATE',
'updateTime', 'yyyy-MM-dd',
'["stat_date","refund_id","refund_type","refund_reason_desc","status","handling_way","negotiate_status"]'::jsonb,
'',
'[]'::jsonb,
'[
{"sourceField":"stat_date","targetField":"stat_date","fieldType":"DATE"},
{"sourceField":"refundId","targetField":"refund_id","fieldType":"BIGINT","defaultValue":0},
{"sourceField":"refundType","targetField":"refund_type","fieldType":"INT","defaultValue":0},
{"sourceField":"refundReasonDesc","targetField":"refund_reason_desc","fieldType":"VARCHAR"},
{"sourceField":"status","targetField":"status","fieldType":"INT","defaultValue":0},
{"sourceField":"handlingWay","targetField":"handling_way","fieldType":"INT","defaultValue":0},
{"sourceField":"negotiateStatus","targetField":"negotiate_status","fieldType":"INT","defaultValue":0},
{"sourceField":"refundId","targetField":"refund_count","fieldType":"INT","aggregateFunction":"COUNT","defaultValue":0},
{"sourceField":"refundFee","targetField":"refund_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0}
]'::jsonb,
'[
{"ruleCode":"ts_to_date","ruleType":"FORMAT","expression":"","format":"yyyy-MM-dd","sourceField":"createTime","targetField":"stat_date"}
]'::jsonb,
500, 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, extract_code) DO NOTHING;
-- ----------------------------------------------------------
-- 4.4 分销订单分析 - AGGREGATE 聚合抽取
-- 源: kuaishou_cps_order_list → 目标: kuaishou_cps_order_stat
-- ----------------------------------------------------------
INSERT INTO report_extract_config (tenant_id, business_code, report_code, extract_code, extract_name, source_table_name, source_table_alias, target_table_name, is_enabled, extract_type, extract_mode, extract_key_field, extract_key_format, group_by_fields, filter_expression, join_configs, field_mappings, transform_rules, batch_size, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'cps_order_analysis', 'cps_order_daily_stat', '分销订单每日统计抽取',
'kuaishou_cps_order_list', 'c',
'kuaishou_cps_order_stat', true, 'INCREMENTAL', 'AGGREGATE',
'updateTime', 'yyyy-MM-dd',
'["stat_date","oid","status","distributor_name","order_channel","settlement_biz_type"]'::jsonb,
'',
'[]'::jsonb,
'[
{"sourceField":"stat_date","targetField":"stat_date","fieldType":"DATE"},
{"sourceField":"oid","targetField":"oid","fieldType":"BIGINT","defaultValue":0},
{"sourceField":"status","targetField":"status","fieldType":"INT","defaultValue":0},
{"sourceField":"distributorName","targetField":"distributor_name","fieldType":"VARCHAR"},
{"sourceField":"orderChannel","targetField":"order_channel","fieldType":"VARCHAR"},
{"sourceField":"settlementBizType","targetField":"settlement_biz_type","fieldType":"INT","defaultValue":0},
{"sourceField":"oid","targetField":"order_count","fieldType":"INT","aggregateFunction":"COUNT","defaultValue":0},
{"sourceField":"totalFee","targetField":"total_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"expressFee","targetField":"express_fee","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"estimatedIncome","targetField":"estimated_income","fieldType":"BIGINT","aggregateFunction":"SUM","defaultValue":0},
{"sourceField":"commissionRate","targetField":"commission_rate","fieldType":"BIGINT","aggregateFunction":"AVG","defaultValue":0}
]'::jsonb,
'[
{"ruleCode":"ts_to_date","ruleType":"FORMAT","expression":"","format":"yyyy-MM-dd","sourceField":"createTime","targetField":"stat_date"}
]'::jsonb,
500, 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, extract_code) DO NOTHING;
-- ----------------------------------------------------------
-- 4.5 代发订单分析 - AGGREGATE 聚合抽取
-- 源: kuaishou_dropshipping_order_list → 目标: kuaishou_dropshipping_stat
-- ----------------------------------------------------------
INSERT INTO report_extract_config (tenant_id, business_code, report_code, extract_code, extract_name, source_table_name, source_table_alias, target_table_name, is_enabled, extract_type, extract_mode, extract_key_field, extract_key_format, group_by_fields, filter_expression, join_configs, field_mappings, transform_rules, batch_size, status, creator, created_at, updater, updated_at) VALUES
(1, 'kuaishou_ecommerce', 'dropshipping_analysis', 'dropshipping_daily_stat', '代发订单每日统计抽取',
'kuaishou_dropshipping_order_list', 'd',
'kuaishou_dropshipping_stat', true, 'INCREMENTAL', 'AGGREGATE',
'updateTime', 'yyyy-MM-dd',
'["stat_date","dropshipping_order_code","order_status","dropshipping_status","factory_name","express_company_name","province_name","city_name","order_type","refund_status"]'::jsonb,
'',
'[]'::jsonb,
'[
{"sourceField":"stat_date","targetField":"stat_date","fieldType":"DATE"},
{"sourceField":"dropshippingOrderCode","targetField":"dropshipping_order_code","fieldType":"VARCHAR"},
{"sourceField":"orderStatus","targetField":"order_status","fieldType":"INT","defaultValue":0},
{"sourceField":"dropshippingStatus","targetField":"dropshipping_status","fieldType":"INT","defaultValue":0},
{"sourceField":"factoryName","targetField":"factory_name","fieldType":"VARCHAR"},
{"sourceField":"factoryCode","targetField":"factory_code","fieldType":"VARCHAR"},
{"sourceField":"expressCompanyName","targetField":"express_company_name","fieldType":"VARCHAR"},
{"sourceField":"provinceName","targetField":"province_name","fieldType":"VARCHAR"},
{"sourceField":"cityName","targetField":"city_name","fieldType":"VARCHAR"},
{"sourceField":"orderType","targetField":"order_type","fieldType":"INT","defaultValue":0},
{"sourceField":"refundStatus","targetField":"refund_status","fieldType":"INT","defaultValue":0},
{"sourceField":"dropshippingOrderCode","targetField":"order_count","fieldType":"INT","aggregateFunction":"COUNT","defaultValue":0}
]'::jsonb,
'[
{"ruleCode":"ts_to_date","ruleType":"FORMAT","expression":"","format":"yyyy-MM-dd","sourceField":"createTime","targetField":"stat_date"}
]'::jsonb,
500, 'ACTIVE', 'admin', NOW(), 'admin', NOW())
ON CONFLICT (tenant_id, business_code, report_code, extract_code) DO NOTHING;
-- =============================================
-- 5. 使用说明
-- =============================================
-- 初始化后,按以下步骤使用报表系统:
-- 1. 确保已执行 sql/seed_data_kuaishou.sql 同步源表数据
-- 2. 在管理后台「业务管理」确认快手电商业务已加载
-- 3. 在「报表配置」点击「自动建表」为每个报表创建统计宽表
-- 4. 在「抽取配置」点击「执行抽取」指定 stat_date从源表聚合数据到宽表
-- 5. 在「数据查询」选择维度/指标/筛选条件进行查询分析
--
-- 关键设计原则:
-- - sourceField 严格对齐 kuaishou_xxx_list 表的实际列名camelCase
-- - targetField / field_code 使用 snake_case 保持项目内部命名一致
-- - 金额字段源表存分(BIGINT),报表提供衍生元字段(CALCULATED expression / 100.0)
-- - 抽取增量字段统一用 updateTime毫秒时间戳 BIGINT
-- - AGGREGATE 模式按 GROUP BY 维度聚合,非聚合字段取第一条