# 客户数据变更追踪系统使用说明

## 一、系统概述

客户数据变更追踪系统是一个用于记录和追踪客户数据变更历史的功能模块。该系统能够：

1. **自动记录数据变更**：每次客户数据发生变化时，自动保存完整的数据快照
2. **版本管理**：为每个客户的数据维护版本号，支持查看历史版本
3. **字段级变更追踪**：详细记录每个字段的变更内容（旧值→新值）
4. **数据指纹识别**：通过MD5哈希快速判断数据是否真正发生变化

## 二、系统架构

### 2.1 数据库表结构

系统包含两个核心数据表：

#### 1. customer_export_data_history（客户数据历史记录表）
- 保存客户数据的每个版本快照
- 包含完整的客户信息字段
- 记录变更类型（INSERT/UPDATE/DELETE）和变更时间
- 使用数据指纹（MD5）快速判断数据是否变更

#### 2. customer_data_change_log（客户数据变更日志表）
- 记录每个字段的具体变更内容
- 包含字段名称、字段标签、旧值、新值
- 关联历史记录表，支持按版本查询变更详情

### 2.2 核心类说明

#### 实体类
- `CustomerExportDataHistory`：历史记录实体类
- `CustomerDataChangeLog`：变更日志实体类

#### Mapper接口
- `CustomerExportDataHistoryMapper`：历史记录数据访问接口
- `CustomerDataChangeLogMapper`：变更日志数据访问接口

#### 服务类
- `CustomerDataTrackingService`：数据变更追踪核心服务
  - `trackDataChange()`：追踪数据变更
  - `compareAndLogChanges()`：比较数据并记录变更
  - `calculateDataFingerprint()`：计算数据指纹

## 三、部署步骤

### 3.1 执行数据库脚本

执行SQL脚本创建数据表：

```bash
# 脚本位置
src/main/resources/sql/customer_data_tracking.sql
```

该脚本会创建：
- `customer_export_data_history` 表
- `customer_data_change_log` 表
- 为 `customer_export_data` 表的 `customer_name` 字段添加索引

### 3.2 验证Mapper配置

确认以下Mapper XML文件已正确配置：

1. `CustomerExportDataMapper.xml`
   - 已添加 `selectByCustomerName` 方法

2. `CustomerExportDataHistoryMapper.xml`
   - 包含版本查询、历史记录查询等方法

3. `CustomerDataChangeLogMapper.xml`
   - 包含变更日志查询、批量插入等方法

### 3.3 配置Spring Bean

确保以下服务类已注册为Spring Bean（已使用@Service注解）：
- `CustomerDataTrackingService`

## 四、使用方法

### 4.1 自动追踪（推荐）

系统已集成到 `CustomerExportService` 中，在以下场景会自动追踪数据变更：

#### 场景1：导入Excel数据
```java
// 在 importExcelData() 方法中
// 系统会自动为每条新增或更新的数据创建历史记录
customerExportService.importExcelData(file);
```

**追踪逻辑**：
- 新增数据：创建 INSERT 类型的历史记录（版本号=1）
- 更新数据：比较新旧数据，如有变化则创建 UPDATE 类型的历史记录（版本号递增）
- 无变化：不创建历史记录（通过数据指纹判断）

### 4.2 手动追踪

如果需要在其他地方手动追踪数据变更：

```java
@Autowired
private CustomerDataTrackingService trackingService;

// 追踪数据变更
trackingService.trackDataChange(newData, "INSERT"); // 新增
trackingService.trackDataChange(newData, "UPDATE"); // 更新
trackingService.trackDataChange(oldData, "DELETE"); // 删除
```

### 4.3 查询历史记录

#### 查询客户的所有历史版本
```java
@Autowired
private CustomerExportDataHistoryMapper historyMapper;

// 查询某个客户的所有历史记录
List<CustomerExportDataHistory> historyList =
    historyMapper.selectHistoryByCustomerId(customerId);
```

#### 查询特定版本的数据
```java
// 查询客户的第2个版本
CustomerExportDataHistory history =
    historyMapper.selectByCustomerIdAndVersion(customerId, 2);
```

#### 查询最新版本号
```java
// 获取客户的最大版本号
Integer maxVersion =
    historyMapper.selectMaxVersionByCustomerId(customerId);
```

### 4.4 查询变更日志

#### 查询客户的所有变更记录
```java
@Autowired
private CustomerDataChangeLogMapper changeLogMapper;

// 查询某个客户的所有变更日志
List<CustomerDataChangeLog> changeLogs =
    changeLogMapper.selectChangeLogByCustomerId(customerId);
```

#### 查询特定版本的变更详情
```java
// 查询客户第2个版本的变更内容
List<CustomerDataChangeLog> changeLogs =
    changeLogMapper.selectChangeLogByCustomerIdAndVersion(customerId, 2);
```

## 五、数据示例

### 5.1 历史记录示例

| history_id | customer_id | version | change_type | change_time | customer_name | mobile | ... |
|------------|-------------|---------|-------------|-------------|---------------|--------|-----|
| 1 | 100 | 1 | INSERT | 2024-01-01 10:00:00 | 张三 | 13800138000 | ... |
| 2 | 100 | 2 | UPDATE | 2024-01-02 14:30:00 | 张三 | 13900139000 | ... |
| 3 | 100 | 3 | UPDATE | 2024-01-03 09:15:00 | 张三 | 13900139000 | ... |

### 5.2 变更日志示例

| log_id | customer_id | version | field_name | field_label | old_value | new_value | change_time |
|--------|-------------|---------|------------|-------------|-----------|-----------|-------------|
| 1 | 100 | 2 | mobile | 手机号 | 13800138000 | 13900139000 | 2024-01-02 14:30:00 |
| 2 | 100 | 3 | company | 公司名称 | ABC公司 | XYZ公司 | 2024-01-03 09:15:00 |
| 3 | 100 | 3 | position | 职位 | 经理 | 总监 | 2024-01-03 09:15:00 |

## 六、常见查询SQL

### 6.1 查询某个客户的所有历史版本
```sql
SELECT *
FROM customer_export_data_history
WHERE customer_id = 100
ORDER BY version DESC;
```

### 6.2 查询某个客户的所有变更日志
```sql
SELECT *
FROM customer_data_change_log
WHERE customer_id = 100
ORDER BY change_time DESC;
```

### 6.3 查询某个版本的具体变更内容
```sql
SELECT *
FROM customer_data_change_log
WHERE customer_id = 100 AND version = 2;
```

### 6.4 查询最近的变更记录（所有客户）
```sql
SELECT *
FROM customer_data_change_log
ORDER BY change_time DESC
LIMIT 100;
```

### 6.5 统计每个客户的版本数量
```sql
SELECT customer_id, COUNT(*) as version_count
FROM customer_export_data_history
GROUP BY customer_id;
```

### 6.6 查询某个时间段内的所有变更
```sql
SELECT *
FROM customer_data_change_log
WHERE change_time BETWEEN '2024-01-01' AND '2024-01-31'
ORDER BY change_time DESC;
```

## 七、性能优化建议

### 7.1 索引优化
系统已为关键字段创建索引：
- `customer_export_data.customer_name`：用于快速查找客户
- `customer_export_data_history.customer_id`：用于查询历史记录
- `customer_export_data_history.version`：用于版本查询
- `customer_data_change_log.customer_id`：用于查询变更日志

### 7.2 数据指纹机制
- 使用MD5哈希值快速判断数据是否变更
- 避免为未变更的数据创建历史记录
- 减少数据库写入操作

### 7.3 批量操作
- 变更日志支持批量插入（`batchInsert`方法）
- 减少数据库交互次数

## 八、注意事项

### 8.1 数据一致性
- 历史记录和变更日志在同一个事务中创建
- 确保数据的一致性和完整性

### 8.2 存储空间
- 历史记录表会保存完整的数据快照
- 随着时间推移，数据量会持续增长
- 建议定期归档或清理过期数据

### 8.3 性能影响
- 每次数据变更都会触发历史记录创建
- 对于大批量导入，会增加一定的处理时间
- 通过数据指纹机制减少不必要的记录

### 8.4 字段映射
- 确保实体类字段名与数据库字段名一致
- 变更日志中的 `field_label` 使用中文标签，便于阅读

## 九、扩展功能建议

### 9.1 数据回滚
可以基于历史记录实现数据回滚功能：
```java
// 将数据回滚到指定版本
public void rollbackToVersion(Long customerId, Integer version) {
    CustomerExportDataHistory history =
        historyMapper.selectByCustomerIdAndVersion(customerId, version);
    // 将历史数据复制到当前数据表
    // ...
}
```

### 9.2 变更统计报表
可以基于变更日志生成统计报表：
- 每日变更数量统计
- 高频变更字段分析
- 用户操作行为分析

### 9.3 变更通知
可以在数据变更时发送通知：
- 邮件通知
- 系统消息通知
- 钉钉/企业微信通知

### 9.4 数据对比界面
可以开发前端界面展示：
- 版本对比视图
- 变更时间线
- 字段变更高亮显示

## 十、故障排查

### 10.1 历史记录未创建
检查项：
1. 数据库表是否正确创建
2. Mapper XML配置是否正确
3. 事务是否正常提交
4. 日志中是否有异常信息

### 10.2 变更日志为空
检查项：
1. 数据是否真正发生变化（通过数据指纹判断）
2. `compareAndLogChanges` 方法是否正常执行
3. 字段比较逻辑是否正确

### 10.3 性能问题
优化方案：
1. 检查索引是否生效
2. 考虑异步处理历史记录创建
3. 批量导入时使用批处理
4. 定期清理过期数据

## 十一、联系支持

如有问题或建议，请联系开发团队。
