# Form Fields Domain

This domain provides services for managing form fields and their associations with record types. It handles the complete lifecycle of form fields and coordinates with the DatabaseColumn domain for database schema management.

## Architecture

The domain follows a clean architecture pattern with the following components:

### Actions
- `CreateFormField` - Handles form field creation with record type associations
- `UpdateFormField` - Handles form field updates and association changes
- `AssociateFormFieldWithRecordType` - Associates a form field with a record type
- `DisassociateFormFieldFromRecordType` - Disassociates a form field from a record type
- `RemoveFormFieldFromRecordType` - Removes a form field from a record type with optional column deletion

### Services
- `FormFieldAssociationService` - Core service for managing form field ↔ record type associations

### Models
- `FormField` - The main form field model with JSON-based record type associations

## Features

- **Form Field Lifecycle Management**: Complete CRUD operations for form fields
- **Record Type Associations**: Many-to-many relationships between form fields and record types
- **Database Column Coordination**: Automatic database column creation when associations are made
- **Data Preservation**: Form fields can be disassociated without losing database columns or data
- **Flexible Associations**: Form fields can be associated with multiple record types
- **Audit Trail**: Track association changes and database column operations

## Usage Examples

### Creating a Form Field with Associations

```php
use Domain\FormFields\Actions\CreateFormField;
use Domain\FormFields\Services\FormFieldAssociationService;

class FormFieldController extends Controller
{
    public function store(Request $request)
    {
        $createFormField = app(CreateFormField::class);

        $result = $createFormField->create([
            'title' => 'Custom Field',
            'content_type' => 8, // free_form_text
            'is_required' => true,
            'recordtypes' => [1, 2, 3] // Multiple record type IDs
        ]);

        if ($result['success']) {
            return response()->json([
                'message' => 'Form field created successfully',
                'field' => $result['record'],
                'associations' => $result['associations']
            ]);
        }

        return response()->json(['error' => $result['message']], 422);
    }
}
```

### Managing Associations

```php
use Domain\FormFields\Actions\AssociateFormFieldWithRecordType;
use Domain\FormFields\Actions\DisassociateFormFieldFromRecordType;
use Domain\FormFields\Actions\RemoveFormFieldFromRecordType;

class FormFieldAssociationController extends Controller
{
    public function associate(Request $request)
    {
        $formField = FormField::findOrFail($request->form_field_id);
        $recordType = RecordType::findOrFail($request->record_type_id);

        $action = app(AssociateFormFieldWithRecordType::class);
        $result = $action->execute($formField, $recordType);

        return response()->json($result);
    }

    public function disassociate(Request $request)
    {
        $formField = FormField::findOrFail($request->form_field_id);
        $recordType = RecordType::findOrFail($request->record_type_id);

        $action = app(DisassociateFormFieldFromRecordType::class);
        $result = $action->execute($formField, $recordType);

        return response()->json($result);
    }

    public function remove(Request $request)
    {
        $formField = FormField::findOrFail($request->form_field_id);
        $recordType = RecordType::findOrFail($request->record_type_id);
        $deleteColumn = $request->boolean('delete_column', false);

        $action = app(RemoveFormFieldFromRecordType::class);
        $result = $action->execute($formField, $recordType, $deleteColumn);

        return response()->json($result);
    }
}
```

### Using the Association Service Directly

```php
use Domain\FormFields\Services\FormFieldAssociationService;

class CustomFormFieldService
{
    public function __construct(
        private FormFieldAssociationService $associationService
    ) {}

    public function addFieldToMultipleRecordTypes(FormField $formField, array $recordTypeIds)
    {
        $results = [];

        foreach ($recordTypeIds as $recordTypeId) {
            $recordType = RecordType::find($recordTypeId);
            if ($recordType) {
                $result = $this->associationService->associateWithRecordType($formField, $recordType);
                $results[] = [
                    'record_type_id' => $recordTypeId,
                    'success' => $result['success'],
                    'message' => $result['message']
                ];
            }
        }

        return $results;
    }
}
```

## Record Type Associations

### Current Implementation
Form fields use a JSON column `record_types` to store an array of record type IDs:

```php
// Form field with multiple record type associations
$formField = FormField::create([
    'title' => 'Custom Field',
    'record_types' => json_encode([1, 2, 3]) // Associated with record types 1, 2, and 3
]);
```

### Association Operations

#### Adding Associations
When a form field is associated with a record type:
1. The record type ID is added to the `record_types` JSON array
2. A corresponding database column is created in the record type's table
3. The column is configured based on the form field's content type and properties

#### Removing Associations
When a form field is disassociated from a record type:
1. The record type ID is removed from the `record_types` JSON array
2. **The database column is preserved** to maintain data integrity
3. Optionally, the column can be deleted if explicitly requested

## Integration with DatabaseColumn Domain

The FormField domain coordinates with the DatabaseColumn domain through the `FormFieldAssociationService`:

### Column Creation
- Form field properties are mapped to column definitions
- Content types are converted to appropriate database column types
- Constraints are applied based on form field settings

### Column Management
- Columns are created when associations are made
- Columns are preserved when associations are removed (by default)
- Columns can be explicitly deleted when needed

## Content Type Mapping

Form fields support various content types that map to database column types:

| Content Type ID | Content Type Slug | Database Column Type |
|----------------|------------------|---------------------|
| 1 | check_box | boolean |
| 2 | currency | decimal |
| 3 | date | date |
| 4 | date_time | datetime |
| 5 | decimal_number | decimal |
| 8 | free_form_text | text |
| 12 | integer_number | integer |
| 13 | list | unsignedBigInteger |
| 14 | long_text | text |
| 19 | record | unsignedBigInteger |
| 21 | text_area | text |

## Best Practices

1. **Use the Association Service**: Always use `FormFieldAssociationService` for managing associations
2. **Preserve Data**: Default to preserving database columns when disassociating
3. **Handle Errors**: Always check operation results and handle errors appropriately
4. **Audit Changes**: Monitor association changes for debugging and compliance
5. **Coordinate Operations**: Use transactions when multiple operations need to be atomic
6. **Validate Inputs**: Ensure record type IDs exist before attempting associations

## Error Handling

The domain provides comprehensive error handling:
- Database operation failures
- Invalid record type associations
- Column creation conflicts
- Constraint violations
- Transaction rollbacks

## Testing

The domain includes tests for:
- Form field CRUD operations
- Association management
- Database column coordination
- Error scenarios
- Transaction handling

## Contributing

When adding new features:
1. Create appropriate actions for new operations
2. Update the association service if needed
3. Add tests for new functionality
4. Update this documentation
5. Maintain separation of concerns with the DatabaseColumn domain
