307 lines
11 KiB
PHP
307 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Casts\AsArrayOfDiscount;
|
|
use App\Enums\CodeType;
|
|
use App\Lib\Discount;
|
|
use App\Lib\Helpers\FileStorageHelper;
|
|
use App\Traits\Models\IsCachedAsCollection;
|
|
use App\Traits\Models\ActivityLog;
|
|
use Carbon\CarbonInterval;
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use LDC\LDCCRM\Enums\Country;
|
|
|
|
/**
|
|
* Settings.
|
|
*
|
|
* @property string $name The game name
|
|
* @property string $company Name of the company that organizes the game
|
|
* @property \Illuminate\Support\Carbon $start_date Start date of the game
|
|
* @property \Illuminate\Support\Carbon $end_date End date of the game
|
|
* @property int $nb_participation_player Max paticipation per player (0 = unlimited)
|
|
* @property int $nb_participation_ip Max paticipation per ip (0 = unlimited)
|
|
* @property int $nb_unique_code_use Max unique code use (0 = unlimited)
|
|
* Dans tous les cas 1 joueur ne peut utiliser
|
|
* qu'une seule fois 1 code donné
|
|
* @property boolean $notify_prize_sent Should the game send notifications
|
|
* when the prize is sent ?
|
|
* @property \App\Enums\CodeType $code_type Wich codes must be used.
|
|
* @property boolean $activated_teaser Is the teaser active ?
|
|
* @property boolean $activated_close_page Is the close page active ?
|
|
* @property \Illuminate\Support\Carbon $close_page_active_date End date of the close page
|
|
* @property string $redirect_close Link to redirect when the game is ended
|
|
* @property boolean $discounts_activated Are the discounts active ?
|
|
* @property string $discounts_site Discount MesBr site
|
|
* @property string $discounts_campaign Discount MesBr campaign
|
|
* @property array<\App\Lib\Discount> $web_coupons Array of web coupons
|
|
* @property array<string> $notification_emails Array of email to notify when there's a winnner
|
|
* @property array<string> $authorized_countries All countries eligible to participate.
|
|
* @property boolean $winning_proof Is the winning proof needed
|
|
* @property-read \Illuminate\Support\Carbon $created_at Creation Date.
|
|
* @property-read \Illuminate\Support\Carbon $updated_at Last update Date.
|
|
*
|
|
* @property-read boolean $game_is_open Le jeu est ouvert ?
|
|
* @property-read boolean $game_has_begun Le jeu à démarré ?
|
|
* @property-read boolean $game_has_ended Le jeu est terminé ?
|
|
* @property-read boolean $should_display_teaser_page Doit afficher la page de teaser ?
|
|
* @property-read boolean $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 ActivityLog;
|
|
use IsCachedAsCollection;
|
|
|
|
/**
|
|
* The attributes that are mass assignable.
|
|
*
|
|
* @var array<int, string>
|
|
*/
|
|
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<string, string>
|
|
*/
|
|
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.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected static function booted()
|
|
{
|
|
static::created(function () {
|
|
self::removeCached();
|
|
});
|
|
static::updated(function (self $model) {
|
|
self::removeCached();
|
|
FileStorageHelper::removeOldFiles(
|
|
$model->fetchCouponsPictures(true),
|
|
$model->fetchCouponsPictures()
|
|
);
|
|
});
|
|
static::deleted(function () {
|
|
self::removeCached();
|
|
});
|
|
}
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Fetch all widget Files
|
|
*
|
|
* @param boolean $useOldAttribute
|
|
* @return array
|
|
*/
|
|
public function fetchCouponsPictures(bool $useOldAttribute = false): array
|
|
{
|
|
$files = [];
|
|
\collect(!$useOldAttribute ? $this->web_coupons : $this->getOriginal('web_coupons'))
|
|
->each(function (Discount $coupon) use (&$files) {
|
|
$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
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function checkGameCanBePlayed(): bool
|
|
{
|
|
/** @var \App\Models\Settings */
|
|
$settings = app(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))
|
|
and !(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))
|
|
and !(bool) Product::getCached()->count()
|
|
) {
|
|
report(new \RuntimeException('Need products to enable the game using ean codes'));
|
|
return false;
|
|
}
|
|
if ($settings->discounts_activated and !(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 ?
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function gameHasBegun(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn (): bool => $this->start_date->lte(now())
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get game_has_ended attribute
|
|
*
|
|
* The game has ended ?
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function gameHasEnded(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn (): bool => $this->game_has_begun and $this->end_date->lte(now())
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get game_is_open attribute
|
|
*
|
|
* The game is oppen ?
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function gameIsOpen(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn (): bool => $this->game_has_begun and !$this->game_has_ended
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get should_display_teaser_page attribute
|
|
*
|
|
* The teaser page has to be displayed ?
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function shouldDisplayTeaserPage(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn (): bool => !$this->game_has_begun and
|
|
!$this->game_has_ended and
|
|
$this->activated_teaser
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get should_display_end_page attribute
|
|
*
|
|
* The end page has to be displayed ?
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function shouldDisplayEndPage(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn (): bool => $this->game_has_begun and
|
|
$this->game_has_ended and
|
|
$this->activated_close_page and
|
|
$this->close_page_active_date->gte(now())
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all authorized countries.
|
|
*
|
|
* @return \Illuminate\Support\Collection
|
|
*/
|
|
public function getAuthorizedCountries(): \Illuminate\Support\Collection
|
|
{
|
|
/** @var \App\Models\Settings $settings */
|
|
$settings = app(Settings::class);
|
|
if (count($settings->authorized_countries)) {
|
|
// * Authorized countries defined in settings.
|
|
$countries = collect(Country::toArray())
|
|
->filter(fn($enum) => in_array($enum->value, $settings->authorized_countries));
|
|
} else {
|
|
// * Only DROM-COM + France.
|
|
$franceCountries = collect(Country::getValidCountries())
|
|
->filter(fn($enum) => !in_array($enum, [Country::belgium(), Country::luxembourg()]));
|
|
$otherCountries = collect(Country::getValidCountries())
|
|
->filter(fn($enum) => !$franceCountries->contains($enum));
|
|
$countries = $franceCountries->merge($otherCountries);
|
|
}
|
|
return $countries;
|
|
}
|
|
|
|
// * RELATIONS
|
|
|
|
/**
|
|
* Activities logs One-to-many relationship.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
|
{
|
|
return $this->hasMany(ActivityLog::class);
|
|
}
|
|
}
|