$web_coupons Array of web coupons * @property array $notification_emails Array of email to notify when there's a winnner * @property array $authorized_countries All countries eligible to participate. * @property bool $winning_proof Is the winning proof needed * @property-read Carbon $created_at Creation Date. * @property-read Carbon $updated_at Last update Date. * @property-read bool $game_is_open Le jeu est ouvert ? * @property-read bool $game_has_begun Le jeu à démarré ? * @property-read bool $game_has_ended Le jeu est terminé ? * @property-read bool $should_display_teaser_page Doit afficher la page de teaser ? * @property-read bool $should_display_end_page Doit afficher la page fin de jeu ? * @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship. */ class Settings extends Model { use HasActivityLog; use IsCachedAsCollection; /** * The attributes that are mass assignable. * * @var list */ #[\Override] protected $fillable = [ 'name', 'company', 'start_date', 'end_date', 'nb_participation_player', 'nb_participation_ip', 'nb_unique_code_use', 'code_type', 'activated_teaser', 'activated_close_page', 'close_page_active_date', 'redirect_close', 'discounts_activated', 'discounts_site', 'discounts_campaign', 'web_coupons', 'authorized_countries', 'notification_emails', 'winning_proof', 'analytics', 'notify_prize_sent', ]; /** * The attributes that should be cast to native types. * * @var array */ #[\Override] protected $casts = [ 'notify_prize_sent' => 'bool', 'code_type' => CodeType::class, 'activated_teaser' => 'bool', 'activated_close_page' => 'bool', 'discounts_activated' => 'bool', 'winning_proof' => 'bool', 'start_date' => 'datetime', 'end_date' => 'datetime', 'close_page_active_date' => 'datetime', 'web_coupons' => AsArrayOfDiscount::class, 'authorized_countries' => 'array', 'notification_emails' => 'array', ]; // * EVENTS /** * Perform any actions required after the model boots. */ protected static function booted(): void { static::created(function (): void { self::removeCached(); }); static::updated(function (self $model): void { self::removeCached(); FileStorageHelper::removeOldFiles( $model->fetchCouponsPictures(true), $model->fetchCouponsPictures() ); }); static::deleted(function (): void { self::removeCached(); }); } // * METHODS /** * Fetch all widget Files */ public function fetchCouponsPictures(bool $useOldAttribute = false): array { $files = []; \collect(! $useOldAttribute ? $this->web_coupons : $this->getOriginal('web_coupons')) ->each(function (Discount $coupon) use (&$files): void { $files = \array_merge($files, [$coupon->picture]); }); return FileStorageHelper::onlyUploadedFilesWithFileStorageHelper(collect($files)->filter()->all()); } /** * Check if the game can be play and report if it cannot. * Methods to check via policy if game can be played * * Needed: * - Min 1 code unique if Settings code_type is unique or both codes. * - Min 1 Instant gagnant. * - Min 1 Product if Settings code_type is ean or both codes. * - Min 1 WebCoupon if Settings discounts_activated */ public function checkGameCanBePlayed(): bool { /** @var Settings */ $settings = resolve(Settings::class); if (! (bool) Prize::getCached()->count()) { report(new RuntimeException('Need prizes to enable the game')); return false; } if ( ($settings->code_type->equals(CodeType::unique) || $settings->code_type->equals(CodeType::both)) && ! (bool) Cache::remember('codes.count', CarbonInterval::day(), fn () => Code::query()->count()) ) { report(new RuntimeException('Need codes to enable the game')); return false; } if (! (bool) InstantWin::getCached()->count()) { report(new RuntimeException('Need instant win to enable the game')); return false; } if ( ($settings->code_type->equals(CodeType::ean) || $settings->code_type->equals(CodeType::both)) && ! (bool) Product::getCached()->count() ) { report(new RuntimeException('Need products to enable the game using ean codes')); return false; } if ($settings->discounts_activated && ! (bool) collect($this->web_coupons)->count()) { report(new RuntimeException('Need MesBr coupons to enable the game using discounts')); return false; } return true; } // * GETTERS /** * Get game_has_begun attribute * * The game has started ? */ protected function gameHasBegun(): Attribute { return Attribute::make( get: fn (): bool => $this->start_date->lte(now()) ); } /** * Get game_has_ended attribute * * The game has ended ? */ protected function gameHasEnded(): Attribute { return Attribute::make( get: fn (): bool => $this->game_has_begun && $this->end_date->lte(now()) ); } /** * Get game_is_open attribute * * The game is oppen ? */ protected function gameIsOpen(): Attribute { return Attribute::make( get: fn (): bool => $this->game_has_begun && ! $this->game_has_ended ); } /** * Get should_display_teaser_page attribute * * The teaser page has to be displayed ? */ protected function shouldDisplayTeaserPage(): Attribute { return Attribute::make( get: fn (): bool => ! $this->game_has_begun && ! $this->game_has_ended && $this->activated_teaser ); } /** * Get should_display_end_page attribute * * The end page has to be displayed ? */ protected function shouldDisplayEndPage(): Attribute { return Attribute::make( get: fn (): bool => $this->game_has_begun && $this->game_has_ended && $this->activated_close_page && $this->close_page_active_date->gte(now()) ); } /** * Get all authorized countries. */ public function getAuthorizedCountries(): Collection { /** @var Settings $settings */ $settings = resolve(Settings::class); if (count($settings->authorized_countries)) { // * Authorized countries defined in settings. return collect(Country::getValidCountries()) ->filter(fn ($enum): bool => in_array($enum->value, $settings->authorized_countries)); } // * Only DROM-COM + France. $franceCountries = collect(Country::getValidCountries()) ->reject(fn ($enum): bool => in_array($enum, [Country::belgium, Country::luxembourg, Country::germany])); $otherCountries = collect(Country::getValidCountries()) ->reject(fn ($enum): bool => $franceCountries->contains($enum)); return $franceCountries->merge($otherCountries); } // * RELATIONS /** * Activities logs One-to-many relationship. * * @return HasMany */ public function activityLogs(): HasMany { return $this->hasMany(ActivityLog::class); } }