ldc-boutique-cnc/app/Models/Discount.php
2022-11-08 15:41:10 +01:00

240 lines
6.6 KiB
PHP

<?php
namespace App\Models;
use App\Enums\DiscountType;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Kwaadpepper\Enum\Traits\CastsEnums;
class Discount extends Model
{
use CastsEnums;
use HasFactory;
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'status' => 'bool',
'date_start' => 'datetime',
'date_end' => 'datetime',
];
/**
* The attributes that should be cast to Enums.
*
* @var array
*/
protected $enumCasts = [
'type' => DiscountType::class,
];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'type', 'discount_value',
'status', 'date_start', 'date_end',
];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
// * EVENT CLOSURES.
static::creating(function (self $model) {
// * ASSERTIONS
self::assertIsAboveZero(
'discount_value',
trans('Valeur de réduction'),
$model->getAttributeFromArray('discount_value')
);
// * TRANSFORMATIONS
$model->makeStatusSense();
});
static::created(function (self $model) {
$model->flashMessages();
});
static::updated(function (self $model) {
$model->flashMessages();
});
static::updating(function (self $model) {
// * ASSERTIONS
self::assertIsAboveZero(
'discount_value',
trans('Valeur de réduction'),
$model->getAttributeFromArray('discount_value')
);
// * TRANSFORMATIONS
$model->makeStatusSense();
});
}
// * RELATIONSHIPS
/**
* BelongsToMany products relation
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products()
{
return $this->belongsToMany(Product::class, 'product_discount');
}
// * METHODS
/**
* Flash boolean attributes modification messages
*
* @param boolean $old Ignore old attribute comparison.
* @return void
*/
public function flashMessages(bool $old = true)
{
$booleanChecks = [
'status' => [
'info' => trans(':model est maintenant pris en compte', [
'model' => Str::singular(trans('models.classes.discounts'))
]),
'warning' => trans(':model n\'est maintenant plus pris en compte', [
'model' => Str::singular(trans('models.classes.discounts'))
])
],
];
$sessionMessages = [];
// * Merge messages
foreach ($booleanChecks as $attribute => $booleanCheck) {
if ($old and $this->getOriginal($attribute) == $this->{$attribute}) {
continue;
}
/** @var string $flashType */
$flashType = \array_keys($booleanCheck)[$this->{$attribute} ? 0 : 1];
if (!\array_key_exists($flashType, $sessionMessages)) {
$sessionMessages[$flashType] = [];
}
$sessionMessages[$flashType][] = $booleanCheck[$flashType];
}
foreach ($sessionMessages as $flashType => $messages) {
session()->flash($flashType, collect($messages)->implode("\n"));
}
}
/**
* Getter displayable_discount_value
*
* @return string
*/
public function getDisplayableDiscountValueAttribute(): string
{
return $this->type->equals(\App\Enums\DiscountType::amount()) ?
number_format($this->discount_value, 2, ',', '') . ' €' :
number_format($this->discount_value, 0) . ' %';
}
/**
* Getter discount_value
*
* @return float
*/
public function getDiscountValueAttribute(): float
{
return $this->type->equals(\App\Enums\DiscountType::amount()) ?
\round(\floatval($this->attributes['discount_value']) / 100, 3) :
\floatval($this->attributes['discount_value']);
}
/**
* Setter discount_value
*
* @param float $value
* @return void
*/
public function setDiscountValueAttribute(float $value): void
{
$this->attributes['discount_value'] =
$this->type->equals(\App\Enums\DiscountType::amount()) ?
\intval(\ceil(\round($value * 100, 3))) :
\intval($value);
}
/**
* Assert Is Above Zero
*
* @param string $attribute
* @param string $name
* @param float $value
* @return void
* @throws \Illuminate\Validation\ValidationException If the value is less or equals to 0.
*/
private static function assertIsAboveZero(string $attribute, string $name, float $value): void
{
Validator::make([
$attribute => $value
], [
$attribute => 'numeric|min:0'
], [], [
$attribute => $name
])->validate();
}
/**
* Adjusts model status using current status and start and end dates
*
* @return void
*/
public function makeStatusSense(): void
{
/** @var \Carbon\Carbon|null */
$date_start = $this->date_start;
/** @var \Carbon\Carbon|null */
$date_end = $this->date_end;
// * Ignore unpublish_at in the past
if ($date_end and $date_end->lessThan(now())) {
return;
}
// * Ignore publish_at in the futur
if ($date_start and $date_start->greaterThan(now())) {
return;
}
if ($date_start or $date_end) {
$this->status = $this->planificated_status;
}
}
/**
* Getter the current status following planification dates
*
* @return boolean
*/
public function getPlanificatedStatusAttribute(): bool
{
/** @var \Carbon\Carbon|null */
$date_start = $this->date_start;
/** @var \Carbon\Carbon|null */
$date_end = $this->date_end;
if ($date_start and $date_end) {
return $date_end->greaterThanOrEqualTo(now()) and $date_start->lessThan(now());
}
if ($date_start) {
return $date_start->lessThan(now());
}
if ($date_end) {
return $date_end->greaterThanOrEqualTo(now());
}
return false;
}
}