Implement multiple phone numbers per workflow feature

Database Changes:
- Added twp_workflow_phones junction table for many-to-many relationship
- Updated activator to create and manage new table
- Maintained backward compatibility with existing phone_number field

Workflow Management:
- Added set_workflow_phone_numbers() and get_workflow_phone_numbers() methods
- Updated get_workflow_by_phone_number() to check both old and new structures
- Enhanced save/update handlers to support phone_numbers array
- Added AJAX endpoint for retrieving workflow phone numbers

User Interface:
- Replaced single phone number select with dynamic multi-select interface
- Added "Add Number" and "Remove" buttons for managing multiple numbers
- Updated workflow listing to display all assigned phone numbers
- Enhanced JavaScript for phone number management and validation

The webhook routing already supports multiple numbers since get_workflow_by_phone_number()
was updated to check both structures. This feature allows users to assign multiple
Twilio phone numbers to trigger the same workflow.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-13 10:35:21 -07:00
parent 30b0cd355f
commit aa58b45501
5 changed files with 254 additions and 19 deletions

View File

@@ -1084,15 +1084,31 @@ class TWP_Workflow {
/**
* Get workflow by phone number
* Now checks both the legacy phone_number field and the new junction table
*/
public static function get_workflow_by_phone_number($phone_number) {
global $wpdb;
$table_name = $wpdb->prefix . 'twp_workflows';
$workflows_table = $wpdb->prefix . 'twp_workflows';
$phones_table = $wpdb->prefix . 'twp_workflow_phones';
return $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE phone_number = %s AND is_active = 1 ORDER BY created_at DESC LIMIT 1",
// First check the new junction table
$workflow = $wpdb->get_row($wpdb->prepare(
"SELECT w.* FROM $workflows_table w
INNER JOIN $phones_table p ON w.id = p.workflow_id
WHERE p.phone_number = %s AND w.is_active = 1
ORDER BY w.created_at DESC LIMIT 1",
$phone_number
));
// If not found, fall back to legacy phone_number field
if (!$workflow) {
$workflow = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $workflows_table WHERE phone_number = %s AND is_active = 1 ORDER BY created_at DESC LIMIT 1",
$phone_number
));
}
return $workflow;
}
/**
@@ -1145,11 +1161,71 @@ class TWP_Workflow {
public static function delete_workflow($workflow_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'twp_workflows';
$phones_table = $wpdb->prefix . 'twp_workflow_phones';
// Delete phone numbers first
$wpdb->delete($phones_table, array('workflow_id' => $workflow_id), array('%d'));
// Then delete workflow
return $wpdb->delete(
$table_name,
array('id' => $workflow_id),
array('%d')
);
}
/**
* Set phone numbers for a workflow
*/
public static function set_workflow_phone_numbers($workflow_id, $phone_numbers) {
global $wpdb;
$phones_table = $wpdb->prefix . 'twp_workflow_phones';
// Remove existing phone numbers for this workflow
$wpdb->delete($phones_table, array('workflow_id' => $workflow_id));
// Add new phone numbers
foreach ($phone_numbers as $phone_number) {
if (!empty($phone_number)) {
$wpdb->insert(
$phones_table,
array(
'workflow_id' => $workflow_id,
'phone_number' => $phone_number
)
);
}
}
return true;
}
/**
* Get phone numbers for a workflow
*/
public static function get_workflow_phone_numbers($workflow_id) {
global $wpdb;
$phones_table = $wpdb->prefix . 'twp_workflow_phones';
$numbers = $wpdb->get_col($wpdb->prepare(
"SELECT phone_number FROM $phones_table WHERE workflow_id = %d",
$workflow_id
));
// If no numbers in junction table, check legacy field
if (empty($numbers)) {
$workflows_table = $wpdb->prefix . 'twp_workflows';
$legacy_number = $wpdb->get_var($wpdb->prepare(
"SELECT phone_number FROM $workflows_table WHERE id = %d",
$workflow_id
));
if ($legacy_number) {
$numbers = array($legacy_number);
// Optionally migrate to new structure
self::set_workflow_phone_numbers($workflow_id, $numbers);
}
}
return $numbers;
}
}