'boolean', 'send_sms' => 'boolean', 'send_whatsapp' => 'boolean', ]; function settingName() { return __eva('Missed Call Configuration'); } function defaultValue() { return [ 'enabled' => false, 'phone_number' => '', 'pbx_provider' => 'other', 'send_sms' => false, 'send_whatsapp' => true, 'delay_seconds' => 0, ]; } public function listItems() { return [ [ 'label' => __eva('Configuration'), 'slug' => 'configuration', 'is_enabled' => (bool) $this->enabled, 'description' => __eva('Configure missed call handling for this restaurant.'), ], ]; } public function fields() { return [ 'configuration' => [ [ 'attribute' => 'webhook_url', 'stacked' => true, 'name' => __eva('Webhook URL'), 'helpText' => __eva('Configure this URL in your PBX provider to receive missed call notifications. Method: POST.'), 'component' => 'webhook-url-field', 'value' => 'alexr_missed_call_webhook', ], [ 'attribute' => 'enabled', 'stacked' => true, 'name' => __eva('Enable Missed Call'), 'helpText' => __eva('Activate the missed call module for this restaurant.'), 'component' => 'boolean-field', 'type' => 'switch', 'value' => $this->enabled, ], [ 'attribute' => 'phone_number', 'stacked' => true, 'name' => __eva('IP Phone Number'), 'helpText' => __eva('The phone number that receives calls and triggers the webhook. Include country code (e.g. +34612345678).'), 'component' => 'text-field', 'value' => $this->phone_number, ], [ 'attribute' => 'pbx_provider', 'stacked' => true, 'name' => __eva('PBX Provider'), 'helpText' => __eva('Select your VoIP/PBX provider.'), 'component' => 'select-field', 'options' => $this->getPbxProviderOptions(), 'value' => $this->pbx_provider, ], [ 'attribute' => 'send_whatsapp', 'stacked' => true, 'name' => __eva('Send WhatsApp'), 'helpText' => __eva('Send a WhatsApp message to the caller after a missed call.'), 'component' => 'boolean-field', 'type' => 'switch', 'value' => $this->send_whatsapp, ], [ 'attribute' => 'send_sms', 'stacked' => true, 'name' => __eva('Send SMS'), 'helpText' => __eva('Send an SMS to the caller after a missed call.'), 'component' => 'boolean-field', 'type' => 'switch', 'value' => $this->send_sms, ], /*[ 'attribute' => 'delay_seconds', 'stacked' => true, 'name' => __eva('Delay before sending'), 'helpText' => __eva('Wait this time before sending the message, in case the restaurant calls back.'), 'component' => 'select-field', 'options' => $this->getDelayOptions(), 'value' => $this->delay_seconds, ],*/ ], ]; } protected function getPbxProviderOptions() { return [ ['label' => __eva('Other'), 'value' => 'other'], ['label' => 'Zadarma', 'value' => 'zadarma'], ['label' => 'Twilio', 'value' => 'twilio'], ['label' => 'CloudTalk', 'value' => 'cloudtalk'], ['label' => 'Telnyx', 'value' => 'telnyx'], ['label' => 'Ringotel', 'value' => 'ringotel'], ]; } protected function getDelayOptions() { return [ ['label' => __eva('Immediately'), 'value' => 0], ['label' => __eva('30 seconds'), 'value' => 30], ['label' => __eva('1 minute'), 'value' => 60], ['label' => __eva('2 minutes'), 'value' => 120], ['label' => __eva('5 minutes'), 'value' => 300], ]; } protected function getWidgetOptions() { $options = [ //['label' => __eva('-- Default widget --'), 'value' => ''], ]; try { $widgets = WidgetForm::where('restaurant_id', $this->restaurant_id)->get(); foreach ($widgets as $widget) { $options[] = [ 'label' => $widget->name ?: __eva('Widget') . ' #' . $widget->id, 'value' => $widget->id, ]; } } catch (\Throwable $e) { // Silently fail — just show default option } return $options; } /** * Find the restaurant that has this phone number configured * * @param string $phone * @return int|null Restaurant ID */ public static function findRestaurantByPhone($phone) { $cleanPhone = preg_replace('/[^0-9+]/', '', $phone); $configs = self::where('meta_key', self::$meta_key)->get(); foreach ($configs as $config) { $configPhone = preg_replace('/[^0-9+]/', '', $config->phone_number ?? ''); if (!empty($configPhone) && self::phonesMatch($cleanPhone, $configPhone)) { //ray('Restaurante encontrado por el telefono: '.$phone.' => '.$config->restaurant_id); return $config->restaurant_id; } } //ray('Restaurante no encontrado por el telefono: '.$phone); return null; } /** * Compare two phone numbers (handles with/without country code prefix) * * @param string $phone1 * @param string $phone2 * @return bool */ protected static function phonesMatch($phone1, $phone2) { // Remove + prefix for comparison $p1 = ltrim($phone1, '+'); $p2 = ltrim($phone2, '+'); // Exact match if ($p1 === $p2) { return true; } // One might be suffix of the other (country code difference) if (strlen($p1) > 6 && strlen($p2) > 6) { return str_ends_with($p1, $p2) || str_ends_with($p2, $p1); } return false; } }