ldc-gen-game-web/app/Models/Participation.php
2026-09-28 16:17:07 +02:00

243 lines
7.2 KiB
PHP

<?php
namespace App\Models;
use App\Casts\Ip;
use App\Lib\Helpers\FileStorageHelper;
use App\Notifications\Customer\PrizeHasBeenSent;
use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use IPLib\Address\AddressInterface;
/**
* Participation.
*
* @property \IPLib\Address\AddressInterface $ip IP
* @property string|null $sticker Path of the sticker file
* @property string|null $ticket Path of the ticket file
* @property string|null $barcode Path of the barcode file
* @property string|null $discount_code Treatment code of the BR
* @property string $comment Administrators comments
* @property boolean $prize_sent Has the won prize been sent ?
* @property-read \Illuminate\Support\Carbon $created_at Creation Date.
* @property-read \Illuminate\Support\Carbon $updated_at Last update Date.
*
* @property-read string|null $ean_code Accessor for ean_code, from product table.
*
* @property-read \App\Models\Customer $customer Associated customer.
* @property-read \App\Models\Code $code Associated code.
* @property-read \App\Models\Product|null $product Associated product.
* @property-read \App\Models\InstantWin $instantWin Associated instantWin.
*
* @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
*/
class Participation extends Model
{
use ActivityLog;
/**
* The attributes that are mass assignable.
*
* @var array<int,string>
*/
protected $fillable = [
'barcode',
'ticket',
'sticker',
'discount_code'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'ip' => Ip::class,
'price_sent' => 'bool'
];
/**
* The model's attributes.
*
* @var array<string,mixed>
*/
protected $attributes = [
'sticker' => null,
'ticket' => null,
'barcode' => null,
'discount_code' => null
];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted(): void
{
static::creating(function (self $model) {
self::manageFields($model);
});
static::updating(function (self $model) {
self::manageFields($model);
/** @var \App\Models\Settings */
$settings = app(Settings::class);
if (
// ? Les notification doivent être envoyées ?
$settings->notify_prize_sent and
// ? On veux marquer le lot comme envoyé ?
$model->prize_sent and
!$model->getOriginal('prize_sent')
) {
/** @var \App\Models\Customer */
$customer = $model->customer;
$customer->notify(new PrizeHasBeenSent());
}
});
static::updated(function (self $model) {
FileStorageHelper::removeOldFile($model, 'barcode');
FileStorageHelper::removeOldFile($model, 'ticket');
FileStorageHelper::removeOldFile($model, 'sticker');
});
static::deleted(function (self $model) {
FileStorageHelper::removeFile($model, 'barcode');
FileStorageHelper::removeFile($model, 'ticket');
FileStorageHelper::removeFile($model, 'sticker');
});
}
// * RELATIONSHIPS
/**
* BelongsTo User relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class);
}
/**
* BelongsTo Codes relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function code(): BelongsTo
{
return $this->belongsTo(Code::class, 'code_unique_id');
}
/**
* BelongsTo Product relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}
/**
* One to one InstantWin relation
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function instantWin(): HasOne
{
return $this->hasOne(InstantWin::class);
}
/**
* 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);
}
// * GETTERS
/**
* Accessor for ean_code, from product table.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute;
*/
public function eanCode(): Attribute
{
return Attribute::make(
get: fn() => optional($this->product)->ean_code,
);
}
// * METHODS
/**
* Make new participation but do not persist on DB
*
* @param \IPLib\Address\AddressInterface $ip Ip for the participation.
* @param \App\Models\Customer $customer The Customer playing the game.
* @param \App\Models\Code|null $code The unique code used to play.
* @param \App\Models\Product|null $product The product that holds the sticker if codes are actived.
* @return \App\Models\Participation
*/
public static function makeNew(
AddressInterface $ip,
Customer $customer,
?Code $code = null,
?Product $product = null
): self {
$self = new self();
$self->ip = $ip;
$self->customer()->associate($customer);
if (!is_null($code)) {
$self->code()->associate($code);
}
if (!is_null($product)) {
$self->product()->associate($product);
}
return $self;
}
/**
* Check if a customer has already won
*
* @param \App\Models\Customer $customer
* @return boolean
*/
public static function customerAlreadyHasAnInstantWin(Customer $customer): bool
{
return self::query()->whereHas('instantWin')
->whereHas('customer', fn(Builder $q) => $q->where('id', $customer->id))
->exists();
}
/**
* Common methods function.
*
* @param self $model
* @return void
*/
private static function manageFields(self $model)
{
if ($model->barcode) {
$model->barcode = FileStorageHelper::storeFile($model, $model->barcode, true);
}
if ($model->ticket) {
$model->ticket = FileStorageHelper::storeFile($model, $model->ticket, true);
}
if ($model->sticker) {
$model->sticker = FileStorageHelper::storeFile($model, $model->sticker, true);
}
if (!$model->comment) {
$model->comment = '';
}
}
}