diff --git a/app/Console/Commands/Services/Services.php b/app/Console/Commands/Services/Services.php index c897c06d..414f4e48 100644 --- a/app/Console/Commands/Services/Services.php +++ b/app/Console/Commands/Services/Services.php @@ -7,6 +7,7 @@ use App\Console\Commands\Services\Tasks\DBMapper; use App\Console\Commands\Services\Tasks\GenerateAlarms; use App\Console\Commands\Services\Tasks\GenerateSetting; use App\Console\Commands\Services\Tasks\MarketsList; +use App\Console\Commands\Services\Tasks\NotifyAlarms; use App\Console\Commands\Services\Tasks\TxoddsFlags; class Services @@ -29,6 +30,9 @@ class Services case 'Generate Alarms': GenerateAlarms::run(); break; + case 'Notify Alarms': + NotifyAlarms::run(); + break; } } diff --git a/app/Console/Commands/Services/Tasks/GenerateSetting.php b/app/Console/Commands/Services/Tasks/GenerateSetting.php index 37de27b5..e2eafabc 100644 --- a/app/Console/Commands/Services/Tasks/GenerateSetting.php +++ b/app/Console/Commands/Services/Tasks/GenerateSetting.php @@ -10,6 +10,7 @@ use App\Models\Client; use App\Models\ComparingBookmaker; use App\Models\MultilineClient; use App\Models\MultilineSetting; +use App\Models\PersonalNotification; use App\Models\Sport; use App\Models\User; use App\Utilities\Notice; @@ -178,5 +179,37 @@ class GenerateSetting } } + /************************************************** + * 5) ALARM NOTIFICATION SETTINGS FOR USERS + **************************************************/ + + if ($debug) { + Notice::note('5) ALARM NOTIFICATION SETTINGS FOR USERS', 'p'); + } + + $users = User::with('client')->get(); + foreach ($users as $user) { + if (in_array($user->id, [1, 2])) { + $sports = Sport::where('is_active', 1)->pluck('id')->toArray(); + } else { + $sports = Client::find($user->client_id)->value('sport'); + } + foreach ($sports as $sport_id) { + foreach ([2, 3] as $alarm_level_id) { + + PersonalNotification::firstOrCreate( + ['sport_id' => $sport_id, 'user_id' => $user->id, 'bookmaker_id' => $user->bookmaker_id, 'alarm_level_id' => $alarm_level_id], + ['notify_by_system' => 0, 'notify_by_email' => 0] + ); + + if ($user->partner_bookmaker_id) { + PersonalNotification::firstOrCreate( + ['sport_id' => $sport_id, 'user_id' => $user->id, 'bookmaker_id' => $user->partner_bookmaker_id, 'alarm_level_id' => $alarm_level_id], + ['notify_by_system' => 0, 'notify_by_email' => 0] + ); + } + } + } + } } } diff --git a/app/Console/Commands/Services/Tasks/NotifyAlarms.php b/app/Console/Commands/Services/Tasks/NotifyAlarms.php new file mode 100644 index 00000000..16e9a895 --- /dev/null +++ b/app/Console/Commands/Services/Tasks/NotifyAlarms.php @@ -0,0 +1,28 @@ +with('event_bookmaker') ->with('event_user_star') ->with('event_user_note') - ->with('event_user_notification') ->where('sport_id', auth()->user()->sport_id) ->where('starttime', '>=', now()); diff --git a/app/Filament/Resources/Events/Tables/EventsTable.php b/app/Filament/Resources/Events/Tables/EventsTable.php index df4ab1ae..a553cbe8 100644 --- a/app/Filament/Resources/Events/Tables/EventsTable.php +++ b/app/Filament/Resources/Events/Tables/EventsTable.php @@ -16,7 +16,6 @@ use App\Models\Country; use App\Models\Event; use App\Models\EventBookmaker; use App\Models\EventUserNote; -use App\Models\EventUserNotification; use App\Models\EventUserStar; use App\Models\Group; use App\Models\OddsTable; @@ -27,11 +26,9 @@ use Filament\Actions\BulkActionGroup; use Filament\Actions\DeleteAction; use Filament\Actions\DeleteBulkAction; use Filament\Forms\Components\Hidden; -use Filament\Forms\Components\Radio; use Filament\Forms\Components\Select; use Filament\Forms\Components\Textarea; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\Toggle; use Filament\Schemas\Components\Utilities\Get; use Filament\Support\Enums\FontWeight; use Filament\Support\Enums\VerticalAlignment; @@ -416,11 +413,6 @@ class EventsTable function (Builder $query, $filter_notes) { $query->whereHas('event_user_note'); } - )->when( - $data['filter_notification'], - function (Builder $query, $filter_notification) { - $query->whereHas('event_user_notification'); - } )->when( $data['favorit_threshold'], function (Builder $query, $favorit_threshold) { @@ -664,77 +656,6 @@ class EventsTable } }) ->color(fn ($record) => $record->event_user_note->isEmpty() ? 'gray' : 'info'), - Action::make('event_notification') - ->modalWidth(Width::Large) - ->modalDescription('Monitoring favorit and if condition is matchted the system will emit a notification') - ->modalSubmitActionLabel('Save') - ->extraModalFooterActions(fn (Action $action, $record) => $record->event_user_notification->isEmpty() ? [] : [$action->makeModalSubmitAction('Delete', arguments: ['delete' => true])->color('danger')]) - ->modalIcon('phosphor-bell') - ->fillForm(data: function ($record) { - foreach ($record->event_user_notification as $value) { - if ($value->user_id == auth()->user()->id && $value->bookmaker_id == auth()->user()->bookmaker_id) { - return [ - 'event_user_notification_id' => $value->id, - 'odds_table_id' => $value->odds_table_id, - 'alarm_level_id' => $value->alarm_level_id, - 'is_notified' => $value->is_notified, - 'notify_by_email' => $value->notify_by_email, - ]; - } - } - - return ['event_user_notification_id' => '']; - }) - ->schema([ - Hidden::make('event_user_notification_id'), - Toggle::make('is_notified')->label('On/Off') - ->onColor('gray') - ->offColor('info'), - Radio::make('odds_table_id') - ->label('Bettype') - ->columns(3) - ->required() - ->options(fn ($record) => OddsTable::options_sport()), - Radio::make('alarm_level_id') - ->label('Alarm level') - ->columns(3) - ->required() - ->options([ - '1' => 'Level 1', - '2' => 'Level 2', - '3' => 'Level 3', - ]), - Toggle::make('notify_by_email')->label('Send also E-Mail') - // ->belowContent('Notify me also by e-mail') - ->onColor('info') - ->offColor('gray'), - ]) - ->icon('phosphor-bell') - ->iconButton() - ->color(fn ($record) => $record?->event_user_notification->isEmpty() ? 'gray' : 'info') - ->action(function ($record, array $data, $arguments = []) { - if ($arguments) { - EventUserNotification::where('id', $data['event_user_notification_id'])->delete(); - } elseif ($data['event_user_notification_id']) { - EventUserNotification::where('id', $data['event_user_notification_id'])->update([ - 'odds_table_id' => $data['odds_table_id'], - 'alarm_level_id' => $data['alarm_level_id'], - 'notify_by_email' => $data['notify_by_email'], - 'is_notified' => $data['is_notified'], - ]); - } else { - EventUserNotification::updateOrCreate([ - 'event_id' => $record->id, - 'bookmaker_id' => auth()->user()->bookmaker_id, - 'user_id' => auth()->user()->id, - ], [ - 'odds_table_id' => $data['odds_table_id'], - 'alarm_level_id' => $data['alarm_level_id'], - 'notify_by_email' => $data['notify_by_email'], - 'is_notified' => $data['is_notified'], - ]); - } - }), ActionGroup::make([ DeleteAction::make()->visible(fn () => auth()->user()->hasRole('super_admin')), Action::make('txodds_odds') diff --git a/app/Filament/Resources/Supervisors/Tables/SupervisorsTable.php b/app/Filament/Resources/Supervisors/Tables/SupervisorsTable.php index d56a9b43..b6a901a6 100644 --- a/app/Filament/Resources/Supervisors/Tables/SupervisorsTable.php +++ b/app/Filament/Resources/Supervisors/Tables/SupervisorsTable.php @@ -78,6 +78,7 @@ class SupervisorsTable 'DB Mapper' => 'DB Mapper', 'Generate Setting' => 'Generate Setting', 'Generate Alarms' => 'Generate Alarms', + 'Notify Alarms' => 'Notify Alarms', ]; case 9: case 10: diff --git a/app/Livewire/PersonalNotificationTable.php b/app/Livewire/PersonalNotificationTable.php new file mode 100644 index 00000000..89f989fa --- /dev/null +++ b/app/Livewire/PersonalNotificationTable.php @@ -0,0 +1,44 @@ +query(PersonalNotification::query()->with('bookmaker')->where('user_id', auth()->user()->id)) + ->columns([ + IconColumn::make('sport.icon') + ->label('') + ->icon(fn ($record) => $record->sport->icon) + ->tooltip(fn ($record) => $record->id), + TextColumn::make('sport.name'), + BookmakerIcon::make('bookmaker.icon')->label('Icon')->size('lg'), + ]); + + } + + public function render(): View + { + return view('livewire.personal-notification-table'); + } +} diff --git a/app/Livewire/UserNotifications.php b/app/Livewire/UserNotifications.php index f364cb94..f61192d4 100644 --- a/app/Livewire/UserNotifications.php +++ b/app/Livewire/UserNotifications.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Mail\UserNotification; +use App\Models\PersonalNotification; use App\Models\User; use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; @@ -13,6 +14,7 @@ use Filament\Notifications\Notification; use Filament\Schemas\Concerns\InteractsWithSchemas; use Filament\Schemas\Contracts\HasSchemas; use Filament\Support\Enums\Width; +use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Concerns\InteractsWithTable; use Filament\Tables\Contracts\HasTable; @@ -27,6 +29,8 @@ class UserNotifications extends Component implements HasActions, HasSchemas, Has use InteractsWithSchemas; use InteractsWithTable; + protected Table $table2; + public function table(Table $table): Table { return $table @@ -48,12 +52,14 @@ class UserNotifications extends Component implements HasActions, HasSchemas, Has ->modalIcon('phosphor-envelope-duotone') ->schema([ Textarea::make('message') + ->required() ->rows(4), Toggle::make('notify_by_email')->label('Send also as email') // ->belowContent('Notify me also by e-mail') ->onColor('info') ->offColor('gray'), ])->action(function (array $data, $record) { + if ($data['notify_by_email']) { Mail::to($record) ->send(new UserNotification($data['message'])); @@ -69,13 +75,23 @@ class UserNotifications extends Component implements HasActions, HasSchemas, Has ->success() ->send(); }), - - ]) - ->toolbarActions([ - // ... ]); } + public function table2(Table $table): Table + { + return $table + ->query(PersonalNotification::query()->where('user_id', auth()->user()->id)) + ->columns([ + IconColumn::make('sport.icon') + ->label('') + ->icon(fn ($record) => $record->sport->icon) + ->tooltip(fn ($record) => $record->id) + ->visibleFrom('lg'), + ]); + + } + public function render(): View { return view('livewire.user-notifications'); diff --git a/app/Models/AlarmLevel.php b/app/Models/AlarmLevel.php new file mode 100644 index 00000000..361c67f1 --- /dev/null +++ b/app/Models/AlarmLevel.php @@ -0,0 +1,10 @@ +hasMany(EventUserNote::class, 'event_id', 'id'); } - public function event_user_notification() - { - return $this->hasMany(EventUserNotification::class, 'event_id', 'id'); - } - public function event_bookmaker() { return $this->hasOne(EventBookmaker::class, 'event_id', 'id')->where('bookmaker_id', auth()->user()->bookmaker_id); diff --git a/app/Models/EventUserNotification.php b/app/Models/PersonalNotification.php similarity index 51% rename from app/Models/EventUserNotification.php rename to app/Models/PersonalNotification.php index a669939a..6c2a9ef5 100644 --- a/app/Models/EventUserNotification.php +++ b/app/Models/PersonalNotification.php @@ -4,31 +4,24 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -class EventUserNotification extends Model +class PersonalNotification extends Model { protected $fillable = [ - 'event_id', - 'bookmaker_id', 'user_id', - 'odds_table_id', + 'sport_id', + 'bookmaker_id', 'alarm_level_id', + 'notify_by_system', 'notify_by_email', - 'is_notified', - 'deleted', ]; - public function user() + public function sport() { - return $this->belongsTo(User::class); + return $this->belongsTo(Sport::class); } public function bookmaker() { return $this->belongsTo(Bookmaker::class); } - - public function odds_table() - { - return $this->belongsTo(OddsTable::class); - } } diff --git a/app/Models/PersonalNotificationSend.php b/app/Models/PersonalNotificationSend.php new file mode 100644 index 00000000..7f8e9e05 --- /dev/null +++ b/app/Models/PersonalNotificationSend.php @@ -0,0 +1,10 @@ +emailVerification() ->emailChangeVerification() ->databaseNotifications() + ->sidebarCollapsibleOnDesktop() // ->databaseNotificationsPolling('15s') default is 30 ->profile(isSimple: false) ->default() diff --git a/database/migrations/2026_02_05_170620_create_personal_notifications_table.php b/database/migrations/2026_02_05_170620_create_personal_notifications_table.php new file mode 100644 index 00000000..81372e62 --- /dev/null +++ b/database/migrations/2026_02_05_170620_create_personal_notifications_table.php @@ -0,0 +1,33 @@ +id(); + $table->integer('user_id')->index()->references('id')->on('users'); + $table->integer('sport_id')->index()->references('id')->on('sports'); + $table->integer('bookmaker_id')->index()->references('id')->on('bookmakers'); + $table->integer('alarm_level_id')->default(0); + $table->boolean('notify_by_system')->default(false); + $table->boolean('notify_by_email')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_notifications'); + } +}; diff --git a/database/migrations/2026_01_30_102545_create_user_notifications_table.php b/database/migrations/2026_02_05_172318_create_personal_notification_sends_table.php similarity index 59% rename from database/migrations/2026_01_30_102545_create_user_notifications_table.php rename to database/migrations/2026_02_05_172318_create_personal_notification_sends_table.php index 813112a1..3be1f530 100644 --- a/database/migrations/2026_01_30_102545_create_user_notifications_table.php +++ b/database/migrations/2026_02_05_172318_create_personal_notification_sends_table.php @@ -11,16 +11,12 @@ return new class extends Migration */ public function up(): void { - Schema::create('event_user_notifications', function (Blueprint $table) { + Schema::create('personal_notification_sends', function (Blueprint $table) { $table->id(); $table->foreignId('event_id')->index()->constrained()->cascadeOnDelete()->references('id')->on('events'); - $table->integer('bookmaker_id')->default(0); $table->integer('user_id')->index()->references('id')->on('users'); - $table->integer('odds_table_id')->index()->references('id')->on('odds_tables'); + $table->integer('bookmaker_id')->index()->references('id')->on('bookmakers'); $table->integer('alarm_level_id')->default(0); - $table->boolean('notify_by_email')->default(false); - $table->boolean('deleted')->default(false); - $table->boolean('is_notified')->default(false); $table->timestamps(); }); } @@ -30,6 +26,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('event_user_notifications'); + Schema::dropIfExists('personal_notification_sends'); } }; diff --git a/database/migrations/2026_02_05_183554_create_alarm_levels_table.php b/database/migrations/2026_02_05_183554_create_alarm_levels_table.php new file mode 100644 index 00000000..47fccdbc --- /dev/null +++ b/database/migrations/2026_02_05_183554_create_alarm_levels_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('name'); + $table->string('color'); + $table->decimal('default_threshold', 3, 2)->default(0); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('alarm_levels'); + } +}; diff --git a/database/seeders/AlarmLevelSeeder.php b/database/seeders/AlarmLevelSeeder.php new file mode 100644 index 00000000..9d6520e8 --- /dev/null +++ b/database/seeders/AlarmLevelSeeder.php @@ -0,0 +1,23 @@ + +