552 lines
16 KiB
Markdown
552 lines
16 KiB
Markdown
# API 文档 - 批量操作
|
||
|
||
## 元数据
|
||
- 需求编号:001-03
|
||
- 创建时间:2026-01-30
|
||
- 创建人:AI Assistant
|
||
- 版本号:v1.0.0
|
||
- 模块:datai-salesforce-partner
|
||
|
||
## API 概述
|
||
|
||
批量操作 API 提供对 Salesforce 记录进行批量操作的能力,支持批量创建、批量更新、批量删除、批量 Upsert 四个核心操作。
|
||
|
||
### 核心特性
|
||
- 支持最多 1000 条记录
|
||
- 自动分批处理(每批最多 200 条)
|
||
- 支持部分失败情况
|
||
- 提供详细的成功/失败统计
|
||
- 支持 AllOrNoneHeader 控制
|
||
- 使用 DisableFeedTrackingHeader 提高性能
|
||
- 批次间休眠时间可配置
|
||
|
||
### 基础信息
|
||
- **Base URL**:`/partner/batch`
|
||
- **认证方式**:JWT Token(通过 Authorization Header 传递)
|
||
- **权限要求**:需要登录权限(`@PreAuthorize("@ss.hasLogin()")`)
|
||
- **Content-Type**:`application/json`
|
||
|
||
## 接口列表
|
||
|
||
### 1. 批量创建记录
|
||
|
||
#### 接口说明
|
||
批量创建 Salesforce 记录,支持最多 1000 条记录,自动分批处理(每批最多 200 条)。
|
||
|
||
#### 请求信息
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/partner/batch/create`
|
||
- **权限要求**:`@ss.hasLogin()`
|
||
|
||
#### 请求参数
|
||
|
||
**Body 参数**:
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| objectType | String | 是 | 对象类型 | "Account" |
|
||
| records | List<Map<String, Object>> | 是 | 记录列表,最多 1000 条 | [{"Name": "Test Account"}] |
|
||
| allOrNone | Boolean | 否 | 是否全部成功或全部失败,默认 false | false |
|
||
| sleepTime | Long | 否 | 批次间休眠时间(毫秒),默认 100 | 100 |
|
||
|
||
#### 响应参数
|
||
|
||
**成功响应**(HTTP 200):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 200 |
|
||
| msg | String | 提示信息 | "批量创建成功" |
|
||
| data | Object | 响应数据 | - |
|
||
| data.success | Boolean | 是否全部成功 | true |
|
||
| data.successCount | Integer | 成功数量 | 100 |
|
||
| data.failureCount | Integer | 失败数量 | 0 |
|
||
| data.totalCount | Integer | 总数量 | 100 |
|
||
| data.results | List | 结果列表 | - |
|
||
| data.results[].success | Boolean | 单项是否成功 | true |
|
||
| data.results[].id | String | 记录 ID | "001xx000003GWFjAAO" |
|
||
| data.results[].errors | List | 错误列表 | [] |
|
||
| data.results[].index | Integer | 索引 | 0 |
|
||
|
||
**失败响应**(HTTP 200,业务失败):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 200 |
|
||
| msg | String | 提示信息 | "批量创建部分失败" |
|
||
| data | Object | 响应数据(包含失败详情) | - |
|
||
|
||
**错误响应**(HTTP 500):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 500 |
|
||
| msg | String | 错误信息 | "批量创建记录失败: ..." |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"objectType": "Account",
|
||
"records": [
|
||
{
|
||
"Name": "Test Account 1",
|
||
"BillingCity": "San Francisco"
|
||
},
|
||
{
|
||
"Name": "Test Account 2",
|
||
"BillingCity": "New York"
|
||
}
|
||
],
|
||
"allOrNone": false,
|
||
"sleepTime": 100
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
**成功示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量创建成功",
|
||
"data": {
|
||
"success": true,
|
||
"successCount": 2,
|
||
"failureCount": 0,
|
||
"totalCount": 2,
|
||
"results": [
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFjAAO",
|
||
"errors": [],
|
||
"index": 0
|
||
},
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFkAAP",
|
||
"errors": [],
|
||
"index": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**部分失败示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量创建部分失败",
|
||
"data": {
|
||
"success": false,
|
||
"successCount": 1,
|
||
"failureCount": 1,
|
||
"totalCount": 2,
|
||
"results": [
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFjAAO",
|
||
"errors": [],
|
||
"index": 0
|
||
},
|
||
{
|
||
"success": false,
|
||
"id": null,
|
||
"errors": [
|
||
{
|
||
"statusCode": "REQUIRED_FIELD_MISSING",
|
||
"message": "Required fields are missing: [Name]",
|
||
"fields": ["Name"]
|
||
}
|
||
],
|
||
"index": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 批量更新记录
|
||
|
||
#### 接口说明
|
||
批量更新 Salesforce 记录,支持最多 1000 条记录,自动分批处理(每批最多 200 条)。每条记录必须包含 `id` 字段。
|
||
|
||
#### 请求信息
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/partner/batch/update`
|
||
- **权限要求**:`@ss.hasLogin()`
|
||
|
||
#### 请求参数
|
||
|
||
**Body 参数**:
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| objectType | String | 是 | 对象类型 | "Account" |
|
||
| records | List<Map<String, Object>> | 是 | 记录列表,每条记录必须包含 id,最多 1000 条 | [{"id": "001xx...", "Name": "Updated"}] |
|
||
| allOrNone | Boolean | 否 | 是否全部成功或全部失败,默认 false | false |
|
||
| sleepTime | Long | 否 | 批次间休眠时间(毫秒),默认 100 | 100 |
|
||
|
||
#### 响应参数
|
||
|
||
**成功响应**(HTTP 200):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 200 |
|
||
| msg | String | 提示信息 | "批量更新成功" |
|
||
| data | Object | 响应数据 | - |
|
||
| data.success | Boolean | 是否全部成功 | true |
|
||
| data.successCount | Integer | 成功数量 | 100 |
|
||
| data.failureCount | Integer | 失败数量 | 0 |
|
||
| data.totalCount | Integer | 总数量 | 100 |
|
||
| data.results | List | 结果列表 | - |
|
||
| data.results[].success | Boolean | 单项是否成功 | true |
|
||
| data.results[].id | String | 记录 ID | "001xx000003GWFjAAO" |
|
||
| data.results[].errors | List | 错误列表 | [] |
|
||
| data.results[].index | Integer | 索引 | 0 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"objectType": "Account",
|
||
"records": [
|
||
{
|
||
"id": "001xx000003GWFjAAO",
|
||
"Name": "Updated Account 1",
|
||
"BillingCity": "Los Angeles"
|
||
},
|
||
{
|
||
"id": "001xx000003GWFkAAP",
|
||
"Name": "Updated Account 2",
|
||
"BillingCity": "Chicago"
|
||
}
|
||
],
|
||
"allOrNone": false,
|
||
"sleepTime": 100
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
**成功示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量更新成功",
|
||
"data": {
|
||
"success": true,
|
||
"successCount": 2,
|
||
"failureCount": 0,
|
||
"totalCount": 2,
|
||
"results": [
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFjAAO",
|
||
"errors": [],
|
||
"index": 0
|
||
},
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFkAAP",
|
||
"errors": [],
|
||
"index": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 批量删除记录
|
||
|
||
#### 接口说明
|
||
批量删除 Salesforce 记录,支持最多 1000 条记录,自动分批处理(每批最多 200 条)。
|
||
|
||
#### 请求信息
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/partner/batch/delete`
|
||
- **权限要求**:`@ss.hasLogin()`
|
||
|
||
#### 请求参数
|
||
|
||
**Body 参数**:
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| objectType | String | 是 | 对象类型 | "Account" |
|
||
| ids | List<String> | 是 | 记录 ID 列表,最多 1000 条 | ["001xx...", "001xx..."] |
|
||
| allOrNone | Boolean | 否 | 是否全部成功或全部失败,默认 false | false |
|
||
| sleepTime | Long | 否 | 批次间休眠时间(毫秒),默认 100 | 100 |
|
||
|
||
#### 响应参数
|
||
|
||
**成功响应**(HTTP 200):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 200 |
|
||
| msg | String | 提示信息 | "批量删除成功" |
|
||
| data | Object | 响应数据 | - |
|
||
| data.success | Boolean | 是否全部成功 | true |
|
||
| data.successCount | Integer | 成功数量 | 100 |
|
||
| data.failureCount | Integer | 失败数量 | 0 |
|
||
| data.totalCount | Integer | 总数量 | 100 |
|
||
| data.results | List | 结果列表 | - |
|
||
| data.results[].success | Boolean | 单项是否成功 | true |
|
||
| data.results[].id | String | 记录 ID | "001xx000003GWFjAAO" |
|
||
| data.results[].errors | List | 错误列表 | [] |
|
||
| data.results[].index | Integer | 索引 | 0 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"objectType": "Account",
|
||
"ids": [
|
||
"001xx000003GWFjAAO",
|
||
"001xx000003GWFkAAP"
|
||
],
|
||
"allOrNone": false,
|
||
"sleepTime": 100
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
**成功示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量删除成功",
|
||
"data": {
|
||
"success": true,
|
||
"successCount": 2,
|
||
"failureCount": 0,
|
||
"totalCount": 2,
|
||
"results": [
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFjAAO",
|
||
"errors": [],
|
||
"index": 0
|
||
},
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFkAAP",
|
||
"errors": [],
|
||
"index": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4. 批量 Upsert 记录
|
||
|
||
#### 接口说明
|
||
批量 Upsert(更新或插入)Salesforce 记录,支持最多 1000 条记录,自动分批处理(每批最多 200 条)。根据指定的外部 ID 字段,如果记录存在则更新,不存在则创建。
|
||
|
||
#### 请求信息
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/partner/batch/upsert`
|
||
- **权限要求**:`@ss.hasLogin()`
|
||
|
||
#### 请求参数
|
||
|
||
**Body 参数**:
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|--------|------|------|------|------|
|
||
| objectType | String | 是 | 对象类型 | "Account" |
|
||
| externalIdField | String | 是 | 外部 ID 字段 | "ExternalId__c" |
|
||
| records | List<Map<String, Object>> | 是 | 记录列表,每条记录必须包含外部 ID 字段,最多 1000 条 | [{"ExternalId__c": "EXT001", "Name": "Test"}] |
|
||
| allOrNone | Boolean | 否 | 是否全部成功或全部失败,默认 false | false |
|
||
| sleepTime | Long | 否 | 批次间休眠时间(毫秒),默认 100 | 100 |
|
||
|
||
#### 响应参数
|
||
|
||
**成功响应**(HTTP 200):
|
||
|
||
| 参数名 | 类型 | 说明 | 示例 |
|
||
|--------|------|------|------|
|
||
| code | Integer | 状态码 | 200 |
|
||
| msg | String | 提示信息 | "批量 Upsert 成功" |
|
||
| data | Object | 响应数据 | - |
|
||
| data.success | Boolean | 是否全部成功 | true |
|
||
| data.successCount | Integer | 成功数量 | 100 |
|
||
| data.failureCount | Integer | 失败数量 | 0 |
|
||
| data.createdCount | Integer | 创建数量 | 50 |
|
||
| data.updatedCount | Integer | 更新数量 | 50 |
|
||
| data.totalCount | Integer | 总数量 | 100 |
|
||
| data.results | List | 结果列表 | - |
|
||
| data.results[].success | Boolean | 单项是否成功 | true |
|
||
| data.results[].id | String | 记录 ID | "001xx000003GWFjAAO" |
|
||
| data.results[].created | Boolean | 是否创建(true 创建,false 更新) | true |
|
||
| data.results[].errors | List | 错误列表 | [] |
|
||
| data.results[].index | Integer | 索引 | 0 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
{
|
||
"objectType": "Account",
|
||
"externalIdField": "ExternalId__c",
|
||
"records": [
|
||
{
|
||
"ExternalId__c": "EXT001",
|
||
"Name": "Upsert Account 1",
|
||
"BillingCity": "Seattle"
|
||
},
|
||
{
|
||
"ExternalId__c": "EXT002",
|
||
"Name": "Upsert Account 2",
|
||
"BillingCity": "Boston"
|
||
}
|
||
],
|
||
"allOrNone": false,
|
||
"sleepTime": 100
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
**成功示例**:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "批量 Upsert 成功",
|
||
"data": {
|
||
"success": true,
|
||
"successCount": 2,
|
||
"failureCount": 0,
|
||
"createdCount": 1,
|
||
"updatedCount": 1,
|
||
"totalCount": 2,
|
||
"results": [
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFjAAO",
|
||
"created": true,
|
||
"errors": [],
|
||
"index": 0
|
||
},
|
||
{
|
||
"success": true,
|
||
"id": "001xx000003GWFkAAP",
|
||
"created": false,
|
||
"errors": [],
|
||
"index": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误码
|
||
|
||
### 系统错误码
|
||
|
||
| 错误码 | 错误消息 | 说明 | 解决方案 |
|
||
|--------|----------|------|----------|
|
||
| 200 | 操作成功 | 请求处理成功 | - |
|
||
| 500 | 操作失败 | 服务器内部错误 | 检查服务器日志,联系管理员 |
|
||
| 401 | 未授权 | 用户未登录或 Token 无效 | 重新登录获取 Token |
|
||
| 403 | 禁止访问 | 用户没有权限执行该操作 | 检查用户权限配置 |
|
||
|
||
### 业务错误码
|
||
|
||
| 错误码 | 错误消息 | 说明 | 解决方案 |
|
||
|--------|----------|------|----------|
|
||
| INVALID_OBJECT_TYPE | 无效的对象类型 | 对象类型不存在或无权限访问 | 检查对象类型名称是否正确 |
|
||
| INVALID_RECORD_ID | 无效的记录 ID | 记录 ID 格式不正确或记录不存在 | 检查记录 ID 是否正确 |
|
||
| INVALID_FIELD_NAME | 无效的字段名称 | 字段名称不存在或无权限访问 | 检查字段名称是否正确 |
|
||
| INVALID_FIELD_VALUE | 无效的字段值 | 字段值不符合要求 | 检查字段值是否符合要求 |
|
||
| MISSING_REQUIRED_FIELD | 缺少必填字段 | 缺少必填字段的值 | 补充必填字段的值 |
|
||
| MISSING_RECORD_ID | 缺少记录 ID | Update 操作必须提供记录 ID | 在记录中添加 id 字段 |
|
||
| MISSING_EXTERNAL_ID | 缺少外部 ID | Upsert 操作必须提供外部 ID 字段 | 在记录中添加外部 ID 字段 |
|
||
| DUPLICATE_VALUE | 重复值 | 字段值已存在,违反唯一性约束 | 检查字段值是否重复 |
|
||
| RECORD_LOCKED | 记录已锁定 | 记录被其他用户锁定 | 等待其他用户释放锁定 |
|
||
| INSUFFICIENT_PERMISSIONS | 权限不足 | 当前用户没有执行该操作的权限 | 检查用户权限配置 |
|
||
| ENTITY_IS_DELETED | 记录已删除 | 记录已被删除 | 检查记录是否存在 |
|
||
| BATCH_SIZE_EXCEEDED | 批量大小超出限制 | 单次批量操作最多支持 1000 条记录 | 减少记录数量 |
|
||
| OPERATION_FAILED | 操作失败 | 操作执行失败 | 检查错误详情 |
|
||
|
||
### Salesforce API 错误码
|
||
|
||
| 错误码 | 说明 |
|
||
|--------|------|
|
||
| REQUIRED_FIELD_MISSING | 缺少必填字段 |
|
||
| INVALID_FIELD | 无效字段 |
|
||
| INVALID_ID_FIELD | 无效 ID 字段 |
|
||
| INVALID_CROSS_REFERENCE_KEY | 无效交叉引用键 |
|
||
| DUPLICATE_VALUE | 重复值 |
|
||
| ENTITY_IS_LOCKED | 实体已锁定 |
|
||
| INSUFFICIENT_ACCESS_OR_READONLY | 权限不足或只读 |
|
||
| INVALID_OPERATION | 无效操作 |
|
||
| STORAGE_LIMIT_EXCEEDED | 存储限制超出 |
|
||
| SYSTEM_UNAVAILABLE | 系统不可用 |
|
||
|
||
## 限制与约束
|
||
|
||
### 数量限制
|
||
- 单次请求最多支持 1000 条记录
|
||
- 每批最多 200 条记录
|
||
- 超出限制将返回 BATCH_SIZE_EXCEEDED 错误
|
||
|
||
### 性能限制
|
||
- 批次间默认休眠 100ms
|
||
- 可根据实际情况调整休眠时间
|
||
- 建议使用 DisableFeedTrackingHeader 提高性能
|
||
|
||
### 权限要求
|
||
- 需要登录权限(`@ss.hasLogin()`)
|
||
- 需要有相应对象的读写权限
|
||
- 需要有相应字段的访问权限
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 分批处理
|
||
对于大规模数据操作,建议使用自动分批处理功能:
|
||
- 单次请求最多 1000 条记录
|
||
- 系统会自动分批处理(每批 200 条)
|
||
- 建议设置适当的批次间休眠时间,避免 API 限流
|
||
|
||
### 2. 错误处理
|
||
- 建议设置 `allOrNone` 为 `false`,允许部分失败
|
||
- 检查返回结果中的 `success` 字段,判断是否全部成功
|
||
- 对于失败的记录,可以查看 `results` 中的错误详情
|
||
|
||
### 3. 性能优化
|
||
- 使用 `DisableFeedTrackingHeader` 提高性能(已默认启用)
|
||
- 设置适当的 `sleepTime`,避免 API 限流
|
||
- 避免在高峰期进行大规模批量操作
|
||
|
||
### 4. Upsert 使用
|
||
- 确保外部 ID 字段在对象中已定义
|
||
- 确保每条记录都包含外部 ID 字段的值
|
||
- 可以使用 `created` 字段判断记录是创建还是更新
|
||
|
||
## 相关文档
|
||
|
||
- [需求文档](../requirements/sub/2026-01-28-001-03-批量操作.md) - 批量操作需求文档
|
||
- [设计文档](../design/2026-01-30-003-批量操作-设计.md) - 批量操作设计文档
|
||
- [决策记录](../decisions/2026-01-30-003-ADR-批量操作技术选型.md) - 批量操作技术选型决策记录
|
||
- [变更日志](../changelog/2026-01-30-003-changelog.md) - 批量操作变更日志
|
||
- [复盘文档](../retros/2026-01-30-003-retro.md) - 批量操作复盘文档
|
||
- [会话记录](../sessions/2026-01-28-001-session.md) - 会话记录
|