'date', 'revoked_at' => 'date', 'last_email_at' => 'datetime', 'monthly_cost' => 'decimal:2', 'selling_price' => 'decimal:2', ]; protected static function boot(): void { parent::boot(); static::creating(function (self $model) { if (empty($model->uuid)) { $model->uuid = (string) Str::uuid(); } }); // Keep ip_pool_contacts in sync whenever contact_email/contact_cc change via normal Eloquent saves. // Bulk import (WithUpserts) bypasses this — call resyncAllContacts() after Excel::import() instead. static::saved(function (self $model) { if ($model->wasChanged(['contact_email', 'contact_cc']) || $model->wasRecentlyCreated) { $model->syncContacts(); } }); } public function network() { return $this->belongsTo(ModuleNetwork::class, 'module_network_id', 'id'); } public function service() { return $this->belongsTo(Service::class, 'service_id'); } public function contacts() { return $this->hasMany(IpPoolContact::class); } /** * contact_email/contact_cc may hold multiple addresses separated by comma/semicolon * (e.g. imported from Google Sheet). Split into a clean array, dropping invalid/empty entries. */ public static function splitEmails(?string $value): array { if (!$value) { return []; } return collect(preg_split('/[,;]+/', $value)) ->map(fn ($e) => trim($e)) ->filter(fn ($e) => $e !== '' && filter_var($e, FILTER_VALIDATE_EMAIL)) ->unique() ->values() ->all(); } public function syncContacts(): void { $rows = []; foreach (self::splitEmails($this->contact_email) as $email) { $rows[] = ['ip_pool_id' => $this->id, 'email' => $email, 'type' => 'to']; } foreach (self::splitEmails($this->contact_cc) as $email) { $rows[] = ['ip_pool_id' => $this->id, 'email' => $email, 'type' => 'cc']; } $this->contacts()->delete(); if ($rows) { IpPoolContact::insert($rows); } } /** * Full resync for bulk paths (CSV import) that bypass the saved() hook above. */ public static function resyncAllContacts(): void { self::withTrashed() ->where(function ($q) { $q->whereNotNull('contact_email')->orWhereNotNull('contact_cc'); }) ->chunkById(500, function ($pools) { foreach ($pools as $pool) { $pool->syncContacts(); } }); } }