# Approval Comments Field Upgrade API

This module provides API endpoints to upgrade old approval comments field configurations in forms to the new steedos-field format, including support for both `current.fields`/`historys.fields` and `amis_schema` transformations.

## Legacy Spec Compliance

This migration tool fully complies with the **"老版本意见栏脚本逻辑规范 (Legacy Approval Script Specs)"** including:

✅ **Logic Inversion:** Correctly converts `only_cc: true` → `show_handler: false` and `only_handler: true` → `show_cc: false`  
✅ **Signature Support:** Detects `signature.traces` keyword and `image_sign` parameter  
✅ **Default Values:** When parameters are undefined, both `show_cc` and `show_handler` default to `true`  
✅ **Parameter Mapping:** All legacy `yijianlan` parameters (`step`, `default`, `only_cc`, `only_handler`, `image_sign`) are correctly mapped  
✅ **Edge Cases:** Empty step names are automatically skipped as invalid configurations  

See the [Special Boolean Logic](#special-boolean-logic) section for detailed mapping.

## Endpoints

### 1. Migrate Endpoint

**GET** `/api/workflow/migrateApprovalCommentsField`

Transforms old approval comments field configurations to the new steedos-field format.

#### Parameters

- `batchSize` (number, optional): Number of bulk operations per batch. Default: 500
- `dryRun` (boolean, optional): When true, simulates the transformation without modifying data. Default: false
- `fid` (string, optional): Flow ID to process only a single flow's form. When provided, only the form associated with this flow will be processed.

#### Request Examples

```bash
# Process all enabled forms
curl -X GET "http://localhost:5000/api/workflow/migrateApprovalCommentsField?dryRun=true" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Process only a specific flow's form
curl -X GET "http://localhost:5000/api/workflow/migrateApprovalCommentsField?fid=flow_id_here" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

#### Response

```json
{
  "totalForms": 10,
  "totalFields": 25,
  "errors": [],
  "dryRun": true,
  "message": "Dry run completed - no changes made"
}
```

#### What It Does

The migration endpoint performs three types of transformations on **enabled forms only** (`state: 'enabled'`):

##### 1. Transform `current.fields` and `historys.fields`

Scans field arrays and matches fields with approval comment patterns in `formula` or `default_value` properties:
- `{traces.XXX}`
- `${traces.XXX}`
- `{signature.traces.XXX}`
- `${signature.traces.XXX}`
- `{yijianlan:...}`

**Important:** Fields with empty step names (e.g., `{traces.}`, `${signature.traces.}`) are automatically skipped. Only fields with valid step names will be transformed.

Transforms matched fields:
- Changes `type` to `steedos-field`
- Adds `__approval_comments_transformed: true` marker
- Stores original type in `__approval_comments_original_type`
- Backs up and removes original `formula` to `__approval_comments_original_formula`
- Backs up and removes original `default_value` to `__approval_comments_original_default_value`
- Adds `config` object with approval comments configuration
- Renames `_amisField` to `__approval_comments_original__amisField` (if exists) and removes original

##### 2. Transform `amis_schema`

Processes the root-level `amis_schema` JSON string:
- Parses the JSON string
- Scans first-level `body` array nodes
- Matches nodes by checking their `value` property (same patterns as above)
- **Important:** Nodes with empty step names (e.g., `{traces.}`) are automatically skipped
- Transforms matched nodes:
  - Changes `type` to `sfield-approvalcomments`
  - Adds `config` object
  - Stores original type in `__approval_comments_original_type`
  - **Removes `value` property** from transformed node
  - Preserves all other original properties (id, label, className, required, etc.)
- Backs up original to `__approval_comments_original__amis_schema`
- Stringifies and saves transformed JSON

**Note:** Only the root `amis_schema` is transformed. `current.amis_schema` and `historys[*].amis_schema` are NOT processed.

##### 3. Handle `_amisField` Property

- If a field has `_amisField`, it's renamed to `__approval_comments_original__amisField`
- The original `_amisField` is removed via `$unset`
- This preserves the original data for perfect rollback

##### 4. Flow-based Filtering (Optional)

When the `fid` parameter is provided:
1. Queries the `flows` collection to find the flow by ID
2. Extracts the `form` property from the flow
3. Filters forms collection to process only that specific form
4. Useful for testing or targeted migrations

#### Transformation Examples

##### Example 1: current.fields Transformation

**Before:**
```json
{
  "code": "部门经理意见",
  "name": "部门领导意见",
  "type": "input",
  "formula": "{yijianlan:{step:'部门经理审核',default:'已阅'}}"
}
```

**After:**
```json
{
  "code": "部门经理意见",
  "name": "部门领导意见",
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "input",
  "__approval_comments_original_formula": "{yijianlan:{step:'部门经理审核',default:'已阅'}}",
  "config": {
    "type": "approval_comments",
    "label": "部门领导意见",
    "object": "",
    "name": "部门经理意见",
    "steps": [
      {
        "name": "部门经理审核",
        "show_cc": true,
        "show_handler": true,
        "show_image_sign": false,
        "default": "已阅"
      }
    ]
  }
}
```

**Note:** Original `formula` is backed up to `__approval_comments_original_formula` and then removed from the field.

##### Example 2: amis_schema Transformation

**Before:**
```json
{
  "type": "input-text",
  "label": "项目所在单位技术发展部",
  "name": "项目所在单位技术发展部",
  "required": true,
  "className": "is_wide",
  "value": "${signature.traces.项目所在单位技术发展部审批}",
  "id": "u:e1562890eed5"
}
```

**After:**
```json
{
  "type": "sfield-approvalcomments",
  "label": "项目所在单位技术发展部",
  "name": "项目所在单位技术发展部",
  "required": true,
  "className": "is_wide",
  "id": "u:e1562890eed5",
  "__approval_comments_original_type": "input-text",
  "config": {
    "type": "approval_comments",
    "label": "项目所在单位技术发展部",
    "object": "",
    "name": "项目所在单位技术发展部",
    "steps": [
      {
        "name": "项目所在单位技术发展部审批",
        "show_cc": true,
        "show_handler": true,
        "show_image_sign": true
      }
    ]
  }
}
```

**Note:** Original `value` property is removed from the transformed node. Original `type` is backed up to `__approval_comments_original_type`.

##### Example 3: _amisField Handling

**Before:**
```json
{
  "code": "test_field",
  "type": "input",
  "formula": "{traces.测试}",
  "_amisField": {
    "label": "测试字段",
    "type": "input-text"
  }
}
```

**After:**
```json
{
  "code": "test_field",
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "input",
  "__approval_comments_original_formula": "{traces.测试}",
  "__approval_comments_original__amisField": {
    "label": "测试字段",
    "type": "input-text"
  },
  "config": {
    "type": "approval_comments",
    "label": "test_field",
    "object": "",
    "name": "test_field",
    "steps": [...]
  }
}
```

**Note:** Original `_amisField` is renamed to `__approval_comments_original__amisField` and removed. Original `formula` is backed up and removed.
Note: Original `_amisField` is removed via `$unset`.

### 2. Rollback Endpoint

**GET** `/api/workflow/rollbackApprovalCommentsField`

Reverts fields that were transformed back to their original format.

#### Parameters

- `batchSize` (number, optional): Number of bulk operations per batch. Default: 500
- `dryRun` (boolean, optional): When true, simulates the rollback without modifying data. Default: false
- `fid` (string, optional): Flow ID to rollback only a single flow's form. When provided, only the form associated with this flow will be processed.

#### Request Examples

```bash
# Rollback all enabled forms
curl -X GET "http://localhost:5000/api/workflow/rollbackApprovalCommentsField" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Rollback only a specific flow's form
curl -X GET "http://localhost:5000/api/workflow/rollbackApprovalCommentsField?fid=flow_id_here" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

#### Response

```json
{
  "totalForms": 10,
  "totalFields": 25,
  "errors": [],
  "dryRun": false,
  "message": "Rollback completed"
}
```

#### What It Does

The rollback endpoint performs three types of restorations on **enabled forms only** (`state: 'enabled'`) with enhanced safety guarantees:

##### 1. Restore `current.fields` and `historys.fields`

**Idempotency (幂等性):**
- Only processes fields marked with `__approval_comments_transformed: true`
- Safe to run multiple times without side effects

**Zero Loss (零丢失):**
1. Restores `type` with priority:
   - **First**: Checks `__approval_comments_original_type` (if stored during migration)
   - **Fallback**: Uses 'input' (for backward compatibility with legacy data)
2. Restores `formula` from `__approval_comments_original_formula` (if exists)
3. Restores `default_value` from `__approval_comments_original_default_value` (if exists)
4. Restores `_amisField` from `__approval_comments_original__amisField` (if exists)
5. This ensures perfect restoration of all original field properties

**Full Coverage (全覆盖):**
- Processes all `historys` array items recursively
- No fields are missed in any history version

**Silent Failure (静默失败):**
- Field-level error handling with try-catch
- Individual field errors don't stop batch processing
- All errors are recorded with detailed context:
  ```json
  {
    "formId": "form_123",
    "formName": "申请表",
    "fieldPath": "current.fields.5",
    "fieldCode": "approval_field",
    "error": "Field data format mismatch"
  }
  ```

**Restoration steps:**
1. Finds forms with fields marked `__approval_comments_transformed: true` and `state: 'enabled'`
2. Restores `type` from `__approval_comments_original_type` (or defaults to 'input')
3. Restores `formula` from `__approval_comments_original_formula` (if exists)
4. Restores `default_value` from `__approval_comments_original_default_value` (if exists)
5. Restores `_amisField` from `__approval_comments_original__amisField` (if exists)
6. Removes added properties:
   - `__approval_comments_transformed`
   - `config`
   - `__approval_comments_original__amisField`
   - `__approval_comments_original_type`
   - `__approval_comments_original_formula`
   - `__approval_comments_original_default_value`

##### 2. Restore `amis_schema`

1. Checks if `__approval_comments_original__amis_schema` exists
2. Restores original `amis_schema` from backup
3. Removes `__approval_comments_original__amis_schema`

This completely restores the amis_schema JSON string to its original state.

##### 3. Restore `_amisField` Property

- If `__approval_comments_origin__amisField` exists, it's restored back to `_amisField`
- The backup property is then removed via `$unset`
- This ensures perfect restoration of the original field structure

#### Rollback Example

**Before Rollback (Transformed):**
```json
{
  "type": "steedos-field",
  "__approval_comments_transformed": true,
  "__approval_comments_original_type": "textarea",
  "__approval_comments_original_formula": "{traces.审批}",
  "__approval_comments_original_default_value": "已阅",
  "__approval_comments_original__amisField": {
    "label": "测试",
    "type": "input-text"
  },
  "config": {...}
}
```

**After Rollback (Restored):**
```json
{
  "type": "textarea",
  "formula": "{traces.审批}",
  "default_value": "已阅",
  "_amisField": {
    "label": "测试",
    "type": "input-text"
  }
}
```

**Zero Loss Guarantee:**
- Original type "textarea" is restored from `__approval_comments_original_type`
- Original `formula` is restored from `__approval_comments_original_formula`
- Original `default_value` is restored from `__approval_comments_original_default_value`
- Original `_amisField` is restored from `__approval_comments_original__amisField`
- Not hardcoded - preserves exact original values
- Backward compatible: Falls back to "input" for type if backup doesn't exist

#### Enhanced Error Handling

Field-level errors are captured with detailed context:

```json
{
  "totalForms": 10,
  "totalFields": 23,
  "errors": [
    {
      "formId": "form-123",
      "formName": "申请表",
      "fieldPath": "current.fields.5",
      "fieldCode": "approval_field",
      "error": "Field data format mismatch"
    }
  ]
}
```

**Silent Failure Benefits:**
- Individual field errors don't stop the batch
- All errors are recorded with field identification
- Easy to trace and fix problematic fields
- Batch processing continues for other fields

## Query Scope and Filtering

### State Filtering

Both migration and rollback endpoints only process forms with `state: 'enabled'`:

```javascript
// Query filter includes
{
  state: 'enabled',
  // ... other conditions
}
```

**Why enabled forms only?**
- Disabled forms are typically archived or deprecated
- Prevents unnecessary processing of inactive forms
- Reduces processing time and potential errors
- Only active production forms are migrated

### Flow-based Filtering (fid Parameter)

When the optional `fid` parameter is provided, only that specific flow's form is processed:

**Migration with fid:**
```bash
GET /api/workflow/migrateApprovalCommentsField?fid=flow_abc123
```

**Rollback with fid:**
```bash
GET /api/workflow/rollbackApprovalCommentsField?fid=flow_abc123
```

**How it works:**
1. Query `flows` collection: `{ _id: fid }`
2. Extract `flow.form` property
3. Add to query filter: `{ _id: flow.form, state: 'enabled' }`

**Use cases:**
- **Testing**: Test migration on a single flow before full rollout
- **Debugging**: Troubleshoot specific flow issues
- **Targeted Updates**: Update only certain flows incrementally
- **Error Recovery**: Re-run migration for specific flows that had errors

**Error handling:**
- If flow not found: Returns error `"Flow with ID {fid} not found"`
- If flow has no form: Returns error `"Flow {fid} does not have a form associated"`

### What Gets Transformed

✅ **Processes:**
- Forms with `state: 'enabled'`
- `current.fields` array (first level only)
- `historys[n].fields` arrays (first level only, all history items)
- Root-level `amis_schema` JSON string

❌ **Does NOT Process:**
- Forms with `state != 'enabled'` (archived, disabled, etc.)
- Nested fields (fields inside fields)
- `current.amis_schema` (not the root one)
- `historys[n].amis_schema` (history-specific schemas)
- Fields without approval comment patterns
- Fields with empty step names (`{traces.}`)

## Security

### Authentication & Authorization

- Both endpoints require authentication
- Only users with `is_space_admin: true` can execute these endpoints
- Proper error messages are returned for unauthorized access

### Data Integrity

- Original field properties are preserved (except `type` and added properties)
- Uses MongoDB's `bulkWrite` with `ordered: false` for atomic operations
- Transformations are reversible using the rollback endpoint
- Dry run mode allows previewing changes before applying

### Performance & Safety

- **Memory Efficient**: Uses MongoDB cursor iteration instead of loading all documents
- **Batch Processing**: BulkWrite operations in configurable batches (default 500)
- **Error Handling**: Errors are logged and returned without stopping entire operation
- **No Code Injection**: Uses safe string matching and JSON parsing

## Configuration Parsing

### Config Object Structure

The `config` object generated during transformation has the following structure:

```json
{
  "type": "approval_comments",
  "label": "<field label>",
  "object": "",
  "name": "<field name or code>",
  "steps": [
    {
      "name": "<step name>",
      "show_cc": true/false,
      "show_handler": true/false,
      "show_image_sign": true/false,
      "default": "<optional default value>"
    }
  ]
}
```

**Key Properties:**
- `type`: Always "approval_comments"
- `label`: From field's `name` or `code` for fields, from `label` or `name` for amis nodes
- `object`: Always empty string ""
- `name`: 
  - For `current.fields`/`historys.fields`: field's `code` or `name`
  - For `amis_schema` nodes: original node's `name` property
- `steps`: Array of step configurations

**Differences between field types:**
- `current.fields`/`historys.fields`: Transform to `type: "steedos-field"` with `config.name = field.code`
- `amis_schema` nodes: Transform to `type: "sfield-approvalcomments"` with `config.name = node.name`

### yijianlan Format

The endpoint handles non-standard JSON format in `{yijianlan:...}`:

```javascript
// Input format (unquoted keys, single quotes for values)
{yijianlan:{step:'部门经理审核',default:'已阅',only_cc:true}}

// Parsed to:
{
  step: "部门经理审核",
  default: "已阅",
  only_cc: true
}
```

### Special Boolean Logic

The migration correctly implements the legacy approval script logic inversion:

- `only_cc: true` → `show_cc: true, show_handler: false`
  - **Legacy behavior:** Show 抄送 (CC), hide 经办人 (Handler)
  - **Logic inversion:** `only_cc` controls whether to hide the handler input
  
- `only_handler: true` → `show_cc: false, show_handler: true`
  - **Legacy behavior:** Hide 抄送 (CC), show 经办人 (Handler)
  - **Logic inversion:** `only_handler` controls whether to hide the CC input
  
- Default (neither specified): `show_cc: true, show_handler: true`
  - **Legacy behavior:** Show both input boxes
  - Both parameters default to `true` when not specified

This follows the "老版本意见栏脚本逻辑规范 (Legacy Approval Script Specs)" exactly.

### Image Sign Detection

- `show_image_sign: true` when:
  - Pattern contains `signature.traces` keyword
  - `yijianlan.image_sign === true`

This maps the legacy electronic signature (电子签章) control to the new format.

### Legacy Parameter Support

The migration supports all legacy `yijianlan` parameters:

| Legacy Parameter | Type | Purpose | New Mapping |
|-----------------|------|---------|-------------|
| `step` | String | Step name (required) | `steps[].name` |
| `default` | String | Default comment text | `steps[].default` |
| `only_cc` | Boolean | Show only CC box | `show_cc: true, show_handler: false` |
| `only_handler` | Boolean | Show only handler box | `show_cc: false, show_handler: true` |
| `image_sign` | Boolean | Enable signature | `show_image_sign: true` |

## Transformation Scope

### What Gets Transformed

**current.fields and historys[].fields:**
- Fields with `formula` or `default_value` matching approval patterns
- Transform to `type: "steedos-field"`
- Only first-level fields (no nested fields)

**amis_schema:**
- Root-level `amis_schema` only (NOT `current.amis_schema` or `historys[*].amis_schema`)
- First-level `body` array nodes with `value` matching approval patterns
- Transform to `type: "sfield-approvalcomments"`
- Preserves all original properties (id, className, required, etc.)

**_amisField:**
- Renamed to `__approval_comments_origin__amisField`
- Original removed via `$unset`

### What Does NOT Get Transformed

- `current.amis_schema` (not processed)
- `historys[*].amis_schema` (not processed)
- Nested fields within `current.fields` or `historys.fields`
- Nested body nodes within amis_schema body array
- Fields without matching patterns
- Fields already transformed (with `__approval_comments_transformed: true`)
- **Fields with empty step names** (e.g., `{traces.}`, `${signature.traces.}`, `{yijianlan:{step:''}}`)
  - These are automatically detected and skipped
  - Only fields with valid, non-empty step names are transformed

### Important: Forms Without amis_schema

Some older forms may not have the `amis_schema` property in the database.

**How Migration Handles This:**
1. Migration checks `if (form.amis_schema)` before processing
2. Forms without `amis_schema` property are skipped during migration
3. Only `current.fields` and `historys.fields` are transformed for these forms
4. `amis_schema` will be generated later when designer opens the form

**Form Designer Fix:**
The form designer endpoint `/api/workflow/form_design` (implemented in `flow_form_design.ejs`) now recognizes the new approval_comments field format in the `getFieldEditTpl()` function (line 274).

When forms don't have `amis_schema`, the designer auto-generates it from `current.fields` at line 172 (`if (!schema)` block). The fix ensures migrated approval_comments fields generate proper `sfield-approvalcomments` AMIS nodes instead of incomplete fields.

**Result:**
- Execution order doesn't matter (migration first or designer first - both work)
- Designer generates correct `sfield-approvalcomments` nodes from migrated fields
- Consistency maintained between `current.fields` and `amis_schema`
- No manual intervention needed

## Pattern Matching Details

### Valid Patterns (Will Transform)
- `{traces.步骤名}` ✓
- `${traces.部门审批}` ✓
- `{signature.traces.技术审核}` ✓
- `${signature.traces.经理审批}` ✓
- `{yijianlan:{step:'部门审核'}}` ✓

### Invalid Patterns (Will Skip)
- `{traces.}` ✗ (empty step name)
- `${traces.}` ✗ (empty step name)
- `{signature.traces.}` ✗ (empty step name)
- `${signature.traces.}` ✗ (empty step name)
- `{yijianlan:{step:''}}` ✗ (empty step name)
- `{yijianlan:{}}` ✗ (no step property)

The regex patterns require at least one character for the step name. Empty step names are automatically filtered out during the `extractStepName()` process.

## Error Handling

Errors are collected and returned in the response:

```json
{
  "totalForms": 10,
  "totalFields": 23,
  "errors": [
    {
      "formId": "form-123",
      "formName": "申请表",
      "error": "Error message"
    }
  ]
}
```

## Best Practices

1. **Always test with dry run first:**
   ```bash
   GET /api/workflow/migrateApprovalCommentsField?dryRun=true
   ```

2. **Backup your database before running the transformation**
   - This is critical as the transformation modifies both field configurations and amis_schema JSON

3. **Use appropriate batch sizes:**
   - Small databases: 500 (default)
   - Large databases with many forms: 100-200
   - Very large databases: Consider running during off-peak hours

4. **Monitor the errors array in the response** to identify any problematic forms
   - Check for JSON parsing errors in amis_schema
   - Verify pattern matching results

5. **Keep the rollback option available** until you've verified the transformation works correctly
   - Test in a staging environment first
   - Verify both field and amis_schema transformations

6. **Verify transformed forms in the UI**
   - Check that approval comments fields render correctly
   - Verify amis form designer still works with transformed schema

7. **Note the differences:**
   - Fields transform to `type: "steedos-field"`
   - Amis nodes transform to `type: "sfield-approvalcomments"`
   - Both get the same `config` structure but with appropriate `name` values


## Rollback Safety Principles

The rollback logic implements four inviolable principles (四大不可逾越原则):

### 1. 幂等性 (Idempotency)
Only processes fields with `__approval_comments_transformed: true` marker.
- **Benefit**: Safe to run multiple times
- **Guarantee**: No duplicate processing
- **Use Case**: Can retry safely if first attempt partially fails

### 2. 零丢失 (Zero Loss)
Prioritizes stored original values for perfect restoration.
- **Primary**: Restores from `__original_type` (stored during migration)
- **Fallback**: Uses 'input' for backward compatibility with legacy data
- **Benefit**: Perfect type restoration (textarea, select, date, etc.)
- **Guarantee**: No data loss, even for complex field types

Example:
```javascript
// Migration stores:
{ type: 'textarea', __original_type: 'textarea', ... }

// Rollback restores:
{ type: 'textarea', ... }  // NOT hardcoded to 'input'
```

### 3. 全覆盖 (Full Coverage)
Recursively processes all historys array items.
- **Coverage**: `current.fields`, `historys[0].fields`, `historys[1].fields`, ..., `historys[n].fields`
- **Benefit**: No field versions are missed
- **Guarantee**: Complete rollback across all form versions

### 4. 静默失败 (Silent Failure)
Field-level error handling with detailed reporting.
- **Isolation**: Individual field errors don't stop batch processing
- **Reporting**: All errors recorded with field identification
- **Benefit**: Maximum data recovery even with problematic fields
- **Guarantee**: Batch processing always completes

Error example:
```json
{
  "formId": "form-123",
  "formName": "申请表",
  "fieldPath": "current.fields.5",
  "fieldCode": "approval_field",
  "error": "Field data format mismatch"
}
```

These principles ensure the rollback operation is:
- ✅ Safe (Idempotent)
- ✅ Complete (Full Coverage)
- ✅ Accurate (Zero Loss)
- ✅ Robust (Silent Failure)


## Monitoring

Check the server logs for detailed information:
- MongoDB connection status
- Processing progress
- Detailed error messages
- Performance metrics

## Limitations

1. **First-level fields only**: Does not process nested fields within fields
2. **First-level body nodes only**: Does not process nested body arrays within amis_schema
3. **Pattern matching**: Only matches the specific patterns listed above
4. **Specific amis_schema only**: Only processes root `amis_schema`, not `current.amis_schema` or `historys[*].amis_schema`
5. **Non-reversible data**: If you manually modify transformed fields, rollback may not work correctly
6. **MongoDB only**: Designed specifically for MongoDB databases

## Troubleshooting

### Issue: Memory errors during migration/rollback

**Symptoms**: Process crashes, out-of-memory errors, or very slow performance

**Solution**: 

1. **Reduce batchSize** to a smaller value (e.g., 200 or 100)
2. **Process specific flows** using the `fid` parameter if needed
   ```bash
   # Example: Use conservative batch size
   curl -X GET "http://localhost:5000/api/workflow/migrateApprovalCommentsField?batchSize=100"
   ```
4. **Run during off-peak hours** when server has more available resources
5. **Process by flow** using the `fid` parameter to handle one flow at a time:
   ```bash
   curl -X GET "http://localhost:5000/api/workflow/migrateApprovalCommentsField?fid=flow_123&batchSize=50"
   ```

### Issue: Migration is too slow

**Symptoms**: Taking too long to process all forms

**Solution**:

1. **Increase batchSize** to a larger value (e.g., 500 or 1000)
2. **Process during off-peak hours** for better performance
   ```bash
   curl -X GET "http://localhost:5000/api/workflow/migrateApprovalCommentsField?batchSize=500"
   ```
4. **For very large databases** (>10,000 forms): Consider using aggressive alternative (1000)

### Issue: Some fields not transformed

**Solution**: 
- For fields: Check if `formula` or `default_value` matches one of the supported patterns
- For amis_schema: Check if node's `value` property matches the patterns
- Ensure field is not already transformed (no `__approval_comments_transformed: true`)
- **Check for empty step names**: Patterns like `{traces.}` with nothing after the dot will be automatically skipped
  - Valid: `{traces.步骤名}`
  - Invalid: `{traces.}` (empty step name - will be skipped)

### Issue: Field has traces pattern but not transforming

**Solution**:
- Verify the step name is not empty: `{traces.XXX}` where XXX must have at least one character
- Check the exact pattern in the formula/default_value property
- Common issue: `{traces.}` with empty step name will be intentionally skipped
- Use dry run mode to see which fields are being processed

### Issue: amis_schema parsing errors

**Solution**: 
- Check server logs for detailed error messages
- Verify the amis_schema is valid JSON
- Ensure the schema has a `body` array property
- Check that body nodes have valid structure

### Issue: yijianlan parsing errors

**Solution**: Check server logs for detailed error messages. The yijianlan format must follow the expected structure: `{yijianlan:{key:'value'}}`

### Issue: Rollback doesn't work

**Solution**: 
- Ensure the field has the `__approval_comments_transformed: true` marker
- Check if backup properties exist (`__approval_comments_origin__amisField`, `__approval_comments_origin__amis_schema`)
- Manual modifications may prevent proper rollback
- Verify no database connection issues

### Issue: amis form designer not working after transformation

**Solution**: 
- Verify the transformed amis_schema is valid JSON
- Check that all required properties (id, type, config) are present
- Try rollback and re-run transformation if needed
