# 数据模型文档

## 1. 数据模型概述

### 1.1 实体关系图 (ER Diagram)

```
┌─────────────────────┐
│  ReportDefinition   │
│  (报表定义)         │
│  ─────────────────  │
│  definition_id PK   │
│  report_code UK     │
│  report_type        │
│  report_name        │
│  parameters JSON    │
│  schedule_cron      │
│  output_formats[]   │
└─────────────────────┘

┌─────────────────────┐       ┌─────────────────────┐
│   ReportSnapshot    │ 1───n │    ReportFile       │
│   (报表快照)        │       │    (报表文件)       │
│  ─────────────────  │       │  ─────────────────  │
│  snapshot_id PK     │       │  file_id PK         │
│  report_code        │       │  snapshot_id FK     │
│  report_period      │       │  file_name          │
│  period_key UK(c)   │       │  file_path          │
│  snapshot_data JSON │       │  file_format        │
│  summary_data JSON  │       │  file_size          │
└─────────────────────┘       └─────────────────────┘

┌─────────────────────┐       ┌─────────────────────┐
│  AnalyticsMetric    │       │ PlantingDailyStat   │
│  (分析指标)         │       │ (认种日统计)        │
│  ─────────────────  │       │  ─────────────────  │
│  metric_id PK       │       │  stat_id PK         │
│  metric_type        │       │  stat_date          │
│  metric_code        │       │  province_code      │
│  dimension_time     │       │  city_code          │
│  metric_value DEC   │       │  order_count        │
│  metric_data JSON   │       │  total_amount DEC   │
└─────────────────────┘       └─────────────────────┘

┌─────────────────────┐       ┌──────────────────────────┐
│   CommunityStat     │       │ SystemAccountMonthlyStat │
│   (社区统计)        │       │ (系统账户月度统计)       │
│  ─────────────────  │       │  ─────────────────────   │
│  stat_id PK         │       │  stat_id PK              │
│  community_id       │       │  account_id              │
│  community_name     │       │  account_type            │
│  stat_date          │       │  stat_month              │
│  total_planting     │       │  monthly_hashpower DEC   │
│  member_count       │       │  cumulative_mining DEC   │
└─────────────────────┘       └──────────────────────────┘

┌──────────────────────────┐   ┌─────────────────────┐
│ SystemAccountIncomeRecord│   │    ReportEvent      │
│ (系统账户收益流水)       │   │    (报表事件)       │
│  ─────────────────────   │   │  ─────────────────  │
│  record_id PK            │   │  event_id PK        │
│  account_id              │   │  event_type         │
│  income_type             │   │  aggregate_id       │
│  income_amount DEC       │   │  aggregate_type     │
│  source_type             │   │  event_data JSON    │
│  occurred_at             │   │  occurred_at        │
└──────────────────────────┘   └─────────────────────┘
```

### 1.2 聚合根划分

| 聚合根 | 表 | 说明 |
|--------|-----|------|
| ReportDefinition | report_definitions | 报表定义,包含配置和调度规则 |
| ReportSnapshot | report_snapshots, report_files | 报表快照,包含生成的文件 |
| AnalyticsMetric | analytics_metrics | 独立的分析指标聚合 |

## 2. 核心表结构

### 2.1 ReportDefinition (报表定义表)

```sql
CREATE TABLE report_definitions (
    definition_id     BIGSERIAL PRIMARY KEY,

    -- 报表基本信息
    report_type       VARCHAR(50) NOT NULL,
    report_name       VARCHAR(200) NOT NULL,
    report_code       VARCHAR(50) NOT NULL UNIQUE,
    description       TEXT,

    -- 报表参数 (JSON)
    parameters        JSONB NOT NULL DEFAULT '{}',

    -- 调度配置
    schedule_cron     VARCHAR(100),
    schedule_timezone VARCHAR(50) DEFAULT 'Asia/Shanghai',
    schedule_enabled  BOOLEAN DEFAULT FALSE,

    -- 输出格式
    output_formats    VARCHAR(20)[] NOT NULL DEFAULT '{}',

    -- 状态
    is_active         BOOLEAN DEFAULT TRUE,

    -- 时间戳
    created_at        TIMESTAMP DEFAULT NOW(),
    updated_at        TIMESTAMP DEFAULT NOW(),
    last_generated_at TIMESTAMP
);

-- 索引
CREATE INDEX idx_def_type ON report_definitions(report_type);
CREATE INDEX idx_def_active ON report_definitions(is_active);
CREATE INDEX idx_def_scheduled ON report_definitions(schedule_enabled);
```

**字段说明:**

| 字段 | 类型 | 说明 |
|------|------|------|
| definition_id | BIGSERIAL | 主键,自增ID |
| report_type | VARCHAR(50) | 报表类型: LEADERBOARD, PLANTING, ANALYTICS 等 |
| report_name | VARCHAR(200) | 报表显示名称 |
| report_code | VARCHAR(50) | 报表唯一编码,用于API调用 |
| description | TEXT | 报表描述说明 |
| parameters | JSONB | 报表参数配置 |
| schedule_cron | VARCHAR(100) | Cron 表达式,定时生成 |
| schedule_timezone | VARCHAR(50) | 调度时区 |
| schedule_enabled | BOOLEAN | 是否启用定时生成 |
| output_formats | VARCHAR(20)[] | 支持的输出格式数组 |
| is_active | BOOLEAN | 是否激活 |
| last_generated_at | TIMESTAMP | 最后生成时间 |

**parameters JSON 结构示例:**

```json
{
  "dataSource": "leaderboard_rankings",
  "aggregation": "daily",
  "filters": {
    "regionLevel": "province",
    "minScore": 100
  },
  "columns": [
    { "field": "rank", "label": "排名" },
    { "field": "userName", "label": "用户名" },
    { "field": "score", "label": "积分" }
  ]
}
```

### 2.2 ReportSnapshot (报表快照表)

```sql
CREATE TABLE report_snapshots (
    snapshot_id       BIGSERIAL PRIMARY KEY,

    -- 报表信息
    report_type       VARCHAR(50) NOT NULL,
    report_code       VARCHAR(50) NOT NULL,
    report_period     VARCHAR(20) NOT NULL,
    period_key        VARCHAR(30) NOT NULL,

    -- 快照数据
    snapshot_data     JSONB NOT NULL,
    summary_data      JSONB,

    -- 数据来源
    data_sources      VARCHAR(100)[] DEFAULT '{}',
    data_freshness    INTEGER DEFAULT 0,

    -- 过滤条件
    filter_params     JSONB,

    -- 统计信息
    row_count         INTEGER DEFAULT 0,

    -- 时间范围
    period_start_at   TIMESTAMP NOT NULL,
    period_end_at     TIMESTAMP NOT NULL,

    -- 时间戳
    generated_at      TIMESTAMP DEFAULT NOW(),
    expires_at        TIMESTAMP,

    UNIQUE(report_code, period_key)
);

-- 索引
CREATE INDEX idx_snapshot_type ON report_snapshots(report_type);
CREATE INDEX idx_snapshot_code ON report_snapshots(report_code);
CREATE INDEX idx_snapshot_period ON report_snapshots(period_key);
CREATE INDEX idx_snapshot_generated ON report_snapshots(generated_at DESC);
CREATE INDEX idx_snapshot_expires ON report_snapshots(expires_at);
```

**字段说明:**

| 字段 | 类型 | 说明 |
|------|------|------|
| snapshot_id | BIGSERIAL | 主键 |
| report_type | VARCHAR(50) | 报表类型 |
| report_code | VARCHAR(50) | 报表编码 |
| report_period | VARCHAR(20) | 报表周期: DAILY, WEEKLY, MONTHLY, YEARLY |
| period_key | VARCHAR(30) | 周期标识: 2024-01-15, 2024-W03, 2024-01 |
| snapshot_data | JSONB | 报表数据内容 |
| summary_data | JSONB | 汇总数据 |
| data_sources | VARCHAR(100)[] | 数据来源服务列表 |
| data_freshness | INTEGER | 数据新鲜度(秒) |
| filter_params | JSONB | 应用的过滤参数 |
| row_count | INTEGER | 数据行数 |
| period_start_at | TIMESTAMP | 周期开始时间 |
| period_end_at | TIMESTAMP | 周期结束时间 |
| generated_at | TIMESTAMP | 生成时间 |
| expires_at | TIMESTAMP | 过期时间 |

**snapshot_data JSON 结构示例:**

```json
{
  "items": [
    {
      "rank": 1,
      "userId": "12345",
      "userName": "张三",
      "score": 9850,
      "treeCount": 100,
      "region": "广东省"
    }
  ],
  "metadata": {
    "totalRecords": 1000,
    "generatedAt": "2024-01-15T08:00:00Z",
    "version": "1.0"
  }
}
```

### 2.3 ReportFile (报表文件表)

```sql
CREATE TABLE report_files (
    file_id           BIGSERIAL PRIMARY KEY,
    snapshot_id       BIGINT NOT NULL REFERENCES report_snapshots(snapshot_id) ON DELETE CASCADE,

    -- 文件信息
    file_name         VARCHAR(500) NOT NULL,
    file_path         VARCHAR(1000) NOT NULL,
    file_url          VARCHAR(1000),
    file_size         BIGINT NOT NULL,
    file_format       VARCHAR(20) NOT NULL,
    mime_type         VARCHAR(100) NOT NULL,

    -- 访问信息
    download_count    INTEGER DEFAULT 0,
    last_download_at  TIMESTAMP,

    -- 时间戳
    created_at        TIMESTAMP DEFAULT NOW(),
    expires_at        TIMESTAMP
);

-- 索引
CREATE INDEX idx_file_snapshot ON report_files(snapshot_id);
CREATE INDEX idx_file_format ON report_files(file_format);
CREATE INDEX idx_file_created ON report_files(created_at DESC);
```

**字段说明:**

| 字段 | 类型 | 说明 |
|------|------|------|
| file_id | BIGSERIAL | 主键 |
| snapshot_id | BIGINT | 关联的快照ID |
| file_name | VARCHAR(500) | 文件名 |
| file_path | VARCHAR(1000) | 文件存储路径 |
| file_url | VARCHAR(1000) | 文件下载URL |
| file_size | BIGINT | 文件大小(字节) |
| file_format | VARCHAR(20) | 文件格式: EXCEL, CSV, PDF |
| mime_type | VARCHAR(100) | MIME类型 |
| download_count | INTEGER | 下载次数 |
| last_download_at | TIMESTAMP | 最后下载时间 |

### 2.4 AnalyticsMetric (分析指标表)

```sql
CREATE TABLE analytics_metrics (
    metric_id           BIGSERIAL PRIMARY KEY,

    -- 指标信息
    metric_type         VARCHAR(50) NOT NULL,
    metric_code         VARCHAR(50) NOT NULL,

    -- 维度
    dimension_time      DATE,
    dimension_region    VARCHAR(100),
    dimension_user_type VARCHAR(50),
    dimension_right_type VARCHAR(50),

    -- 指标值
    metric_value        DECIMAL(20, 8) NOT NULL,
    metric_data         JSONB,

    -- 时间戳
    calculated_at       TIMESTAMP DEFAULT NOW(),

    UNIQUE(metric_code, dimension_time, dimension_region, dimension_user_type, dimension_right_type)
);

-- 索引
CREATE INDEX idx_metric_type ON analytics_metrics(metric_type);
CREATE INDEX idx_metric_code ON analytics_metrics(metric_code);
CREATE INDEX idx_metric_time ON analytics_metrics(dimension_time);
CREATE INDEX idx_metric_region ON analytics_metrics(dimension_region);
```

**指标类型 (metric_type):**

| 类型 | 说明 |
|------|------|
| PLANTING_COUNT | 认种数量 |
| PLANTING_AMOUNT | 认种金额 |
| USER_ACTIVE | 活跃用户数 |
| REVENUE_TOTAL | 总收益 |
| HASHPOWER_DAILY | 日算力 |

## 3. 统计表结构

### 3.1 PlantingDailyStat (认种日统计表)

```sql
CREATE TABLE planting_daily_stats (
    stat_id           BIGSERIAL PRIMARY KEY,

    -- 统计日期
    stat_date         DATE NOT NULL,

    -- 区域维度
    province_code     VARCHAR(10),
    city_code         VARCHAR(10),

    -- 统计数据
    order_count       INTEGER DEFAULT 0,
    tree_count        INTEGER DEFAULT 0,
    total_amount      DECIMAL(20, 8) DEFAULT 0,
    new_user_count    INTEGER DEFAULT 0,
    active_user_count INTEGER DEFAULT 0,

    -- 时间戳
    created_at        TIMESTAMP DEFAULT NOW(),
    updated_at        TIMESTAMP DEFAULT NOW(),

    UNIQUE(stat_date, province_code, city_code)
);

-- 索引
CREATE INDEX idx_pds_date ON planting_daily_stats(stat_date);
CREATE INDEX idx_pds_province ON planting_daily_stats(province_code);
CREATE INDEX idx_pds_city ON planting_daily_stats(city_code);
```

### 3.2 CommunityStat (社区统计表)

```sql
CREATE TABLE community_stats (
    stat_id             BIGSERIAL PRIMARY KEY,

    -- 社区信息
    community_id        BIGINT NOT NULL,
    community_name      VARCHAR(200) NOT NULL,
    parent_community_id BIGINT,

    -- 统计日期
    stat_date           DATE NOT NULL,

    -- 统计数据
    total_planting      INTEGER DEFAULT 0,
    daily_planting      INTEGER DEFAULT 0,
    weekly_planting     INTEGER DEFAULT 0,
    monthly_planting    INTEGER DEFAULT 0,
    member_count        INTEGER DEFAULT 0,

    -- 时间戳
    created_at          TIMESTAMP DEFAULT NOW(),
    updated_at          TIMESTAMP DEFAULT NOW(),

    UNIQUE(community_id, stat_date)
);

-- 索引
CREATE INDEX idx_cs_community ON community_stats(community_id);
CREATE INDEX idx_cs_name ON community_stats(community_name);
CREATE INDEX idx_cs_date ON community_stats(stat_date);
CREATE INDEX idx_cs_parent ON community_stats(parent_community_id);
```

### 3.3 SystemAccountMonthlyStat (系统账户月度统计表)

```sql
CREATE TABLE system_account_monthly_stats (
    stat_id                   BIGSERIAL PRIMARY KEY,

    -- 账户信息
    account_id                BIGINT NOT NULL,
    account_type              VARCHAR(30) NOT NULL,
    account_name              VARCHAR(200) NOT NULL,
    region_code               VARCHAR(10) NOT NULL,

    -- 统计月份
    stat_month                VARCHAR(7) NOT NULL,  -- 格式: YYYY-MM

    -- 月度数据
    monthly_hashpower         DECIMAL(20, 8) DEFAULT 0,
    cumulative_hashpower      DECIMAL(20, 8) DEFAULT 0,
    monthly_mining            DECIMAL(20, 8) DEFAULT 0,
    cumulative_mining         DECIMAL(20, 8) DEFAULT 0,
    monthly_commission        DECIMAL(20, 8) DEFAULT 0,
    cumulative_commission     DECIMAL(20, 8) DEFAULT 0,
    monthly_planting_bonus    DECIMAL(20, 8) DEFAULT 0,
    cumulative_planting_bonus DECIMAL(20, 8) DEFAULT 0,

    -- 时间戳
    created_at                TIMESTAMP DEFAULT NOW(),
    updated_at                TIMESTAMP DEFAULT NOW(),

    UNIQUE(account_id, stat_month)
);

-- 索引
CREATE INDEX idx_sams_type ON system_account_monthly_stats(account_type);
CREATE INDEX idx_sams_month ON system_account_monthly_stats(stat_month);
CREATE INDEX idx_sams_region ON system_account_monthly_stats(region_code);
```

**account_type 枚举值:**

| 值 | 说明 |
|-----|------|
| PROVINCE_COMPANY | 省公司账户 |
| CITY_COMPANY | 市公司账户 |
| PLATFORM | 平台账户 |

### 3.4 SystemAccountIncomeRecord (系统账户收益流水表)

```sql
CREATE TABLE system_account_income_records (
    record_id         BIGSERIAL PRIMARY KEY,

    -- 账户信息
    account_id        BIGINT NOT NULL,
    account_type      VARCHAR(30) NOT NULL,

    -- 收益信息
    income_type       VARCHAR(50) NOT NULL,
    income_amount     DECIMAL(20, 8) NOT NULL,
    currency          VARCHAR(10) NOT NULL,

    -- 来源信息
    source_type       VARCHAR(50) NOT NULL,
    source_id         VARCHAR(100),
    source_user_id    BIGINT,
    source_address    VARCHAR(200),
    transaction_no    VARCHAR(100),

    -- 备注
    memo              TEXT,

    -- 时间戳
    occurred_at       TIMESTAMP NOT NULL,
    created_at        TIMESTAMP DEFAULT NOW()
);

-- 索引
CREATE INDEX idx_sair_account ON system_account_income_records(account_id);
CREATE INDEX idx_sair_type ON system_account_income_records(account_type);
CREATE INDEX idx_sair_income_type ON system_account_income_records(income_type);
CREATE INDEX idx_sair_source_type ON system_account_income_records(source_type);
CREATE INDEX idx_sair_address ON system_account_income_records(source_address);
CREATE INDEX idx_sair_txno ON system_account_income_records(transaction_no);
CREATE INDEX idx_sair_occurred ON system_account_income_records(occurred_at DESC);
```

**income_type 枚举值:**

| 值 | 说明 |
|-----|------|
| MINING_REWARD | 挖矿奖励 |
| COMMISSION | 佣金收入 |
| PLANTING_BONUS | 认种奖励 |
| REFERRAL_BONUS | 推荐奖励 |

**source_type 枚举值:**

| 值 | 说明 |
|-----|------|
| PLANTING_ORDER | 认种订单 |
| MINING_SETTLEMENT | 挖矿结算 |
| COMMISSION_SETTLEMENT | 佣金结算 |
| MANUAL_ADJUSTMENT | 手工调整 |

## 4. 事件表

### 4.1 ReportEvent (报表事件表)

```sql
CREATE TABLE report_events (
    event_id        BIGSERIAL PRIMARY KEY,
    event_type      VARCHAR(50) NOT NULL,

    -- 聚合根信息
    aggregate_id    VARCHAR(100) NOT NULL,
    aggregate_type  VARCHAR(50) NOT NULL,

    -- 事件数据
    event_data      JSONB NOT NULL,

    -- 元数据
    user_id         BIGINT,
    occurred_at     TIMESTAMP(6) DEFAULT NOW(),
    version         INTEGER DEFAULT 1
);

-- 索引
CREATE INDEX idx_report_event_aggregate ON report_events(aggregate_type, aggregate_id);
CREATE INDEX idx_report_event_type ON report_events(event_type);
CREATE INDEX idx_report_event_occurred ON report_events(occurred_at);
```

**event_type 枚举值:**

| 值 | 说明 |
|-----|------|
| REPORT_DEFINITION_CREATED | 报表定义创建 |
| REPORT_DEFINITION_UPDATED | 报表定义更新 |
| REPORT_SNAPSHOT_GENERATED | 报表快照生成 |
| REPORT_FILE_EXPORTED | 报表文件导出 |
| REPORT_FILE_DOWNLOADED | 报表文件下载 |

**event_data 示例:**

```json
{
  "snapshotId": "12345",
  "reportCode": "RPT_LEADERBOARD",
  "period": "DAILY",
  "periodKey": "2024-01-15",
  "rowCount": 1000,
  "generatedAt": "2024-01-15T08:00:00Z"
}
```

## 5. 数据字典

### 5.1 报表周期 (ReportPeriod)

| 值 | 说明 | period_key 格式 |
|-----|------|----------------|
| DAILY | 日报 | 2024-01-15 |
| WEEKLY | 周报 | 2024-W03 |
| MONTHLY | 月报 | 2024-01 |
| YEARLY | 年报 | 2024 |
| CUSTOM | 自定义 | 2024-01-01_2024-01-31 |

### 5.2 导出格式 (ExportFormat)

| 值 | MIME类型 | 说明 |
|-----|----------|------|
| EXCEL | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | Excel 2007+ |
| CSV | text/csv | 逗号分隔值 |
| PDF | application/pdf | PDF 文档 |
| JSON | application/json | JSON 格式 |

### 5.3 报表类型 (ReportType)

| 值 | 说明 |
|-----|------|
| LEADERBOARD | 排行榜报表 |
| PLANTING | 认种统计报表 |
| ANALYTICS | 分析报表 |
| COMMUNITY | 社区统计报表 |
| SYSTEM_ACCOUNT | 系统账户报表 |
| INCOME_DETAIL | 收益明细报表 |

## 6. 索引策略

### 6.1 查询模式分析

| 查询场景 | 使用索引 | 频率 |
|---------|---------|------|
| 按报表编码查询快照 | idx_snapshot_code | 高 |
| 按时间范围查询快照 | idx_snapshot_generated | 高 |
| 按周期查询快照 | idx_snapshot_period | 中 |
| 按账户查询收益流水 | idx_sair_account | 高 |
| 按日期查询统计数据 | idx_pds_date, idx_cs_date | 高 |

### 6.2 复合索引建议

```sql
-- 高频查询: 按报表编码和周期查询最新快照
CREATE INDEX idx_snapshot_code_generated
ON report_snapshots(report_code, generated_at DESC);

-- 高频查询: 按账户和月份查询统计
CREATE INDEX idx_sams_account_month
ON system_account_monthly_stats(account_id, stat_month DESC);

-- 高频查询: 按日期和区域查询认种统计
CREATE INDEX idx_pds_date_region
ON planting_daily_stats(stat_date, province_code, city_code);
```

## 7. 数据保留策略

### 7.1 保留周期

| 表 | 保留周期 | 清理策略 |
|-----|---------|---------|
| report_snapshots | 90天 | 按 expires_at 清理 |
| report_files | 30天 | 按 expires_at 清理 |
| analytics_metrics | 365天 | 按 calculated_at 归档 |
| planting_daily_stats | 永久 | 按年归档 |
| system_account_income_records | 永久 | 按年归档 |
| report_events | 180天 | 按 occurred_at 清理 |

### 7.2 清理脚本

```sql
-- 清理过期快照
DELETE FROM report_snapshots
WHERE expires_at IS NOT NULL AND expires_at < NOW();

-- 清理过期文件
DELETE FROM report_files
WHERE expires_at IS NOT NULL AND expires_at < NOW();

-- 清理旧事件
DELETE FROM report_events
WHERE occurred_at < NOW() - INTERVAL '180 days';
```

## 8. Prisma Schema 映射

### 8.1 模型与表映射

| Prisma Model | 数据库表 | 主键映射 |
|--------------|---------|---------|
| ReportDefinition | report_definitions | definition_id |
| ReportSnapshot | report_snapshots | snapshot_id |
| ReportFile | report_files | file_id |
| AnalyticsMetric | analytics_metrics | metric_id |
| PlantingDailyStat | planting_daily_stats | stat_id |
| CommunityStat | community_stats | stat_id |
| SystemAccountMonthlyStat | system_account_monthly_stats | stat_id |
| SystemAccountIncomeRecord | system_account_income_records | record_id |
| ReportEvent | report_events | event_id |

### 8.2 关系映射

```prisma
// ReportSnapshot 1:N ReportFile
model ReportFile {
  snapshot   ReportSnapshot @relation(fields: [snapshotId], references: [id], onDelete: Cascade)
  snapshotId BigInt         @map("snapshot_id")
}
```

### 8.3 类型映射

| Prisma 类型 | PostgreSQL 类型 | 说明 |
|------------|----------------|------|
| BigInt | BIGSERIAL | 大整数主键 |
| String @db.VarChar(n) | VARCHAR(n) | 变长字符串 |
| String @db.Text | TEXT | 长文本 |
| Json | JSONB | JSON 二进制 |
| Decimal @db.Decimal(20,8) | DECIMAL(20,8) | 高精度数值 |
| DateTime | TIMESTAMP | 时间戳 |
| DateTime @db.Date | DATE | 日期 |
| Boolean | BOOLEAN | 布尔值 |
| String[] | VARCHAR(n)[] | 字符串数组 |
