ldc-crm/app/Models/Claim.php
2025-12-01 16:23:45 +01:00

279 lines
8.2 KiB
PHP

<?php
namespace App\Models;
use App\Enums\Claims\ClaimResponseType;
use App\Enums\Claims\ClaimStatus;
use App\Enums\Claims\ClaimType;
use App\Events\ClaimModelChanged;
use App\Interfaces\IsExportable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
/**
* @property integer $id Claim id.
* @property string $reference Claim reference.
* @property string $first_name Claimant\'s first name.
* @property string $last_name Claimant\'s last name.
* @property string $email Claimant\'s email.
* @property string|null $address Claimant\'s address.
* @property string|null $city Claimant\'s city.
* @property string|null $postcode Claimant\'s postcode.
* @property string|null $file Claimant\'s file.
* @property string $message Claimant\'s message.
* @property \App\Enums\Claims\ClaimResponseType $response_type Claim type (ClaimResponseType enum).
* @property \App\Enums\Claims\ClaimStatus $status Claim status (ClaimStatus enum).
* @property \App\Enums\Claims\ClaimType $type Claim type (ClaimType enum).
* @property \App\Models\Brand $brand_id Claim associated Brand.
* @property \App\Models\ClaimSubject $subject_id Claim associated Subject.
* @property string|null $hashcode Claim associated Customer hashcode.
* @property-read \Illuminate\Support\Carbon $created_at Claim created date.
* @property-read \Illuminate\Support\Carbon $updated_at Claim updated date.
*
* @property-read string $file_extension Extension of the file.
* @property-read string $export_file_name Name of the exported file.
*/
class Claim extends Model implements IsExportable
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'reference',
'first_name',
'last_name',
'email',
'address',
'city',
'postcode',
'file',
'message',
'response_type',
'status',
'type',
'brand_id',
'subject_id',
'hashcode',
];
/**
* The attributes that should be cast.
*
* @var array<string, mixed>
*/
protected $casts = [
'response_type' => ClaimResponseType::class,
'status' => ClaimStatus::class,
'type' => ClaimType::class,
];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted(): void
{
static::created(function (self $model) {
$model->reference = self::encodeIntegerToBase36($model->getKey());
$model->saveOrFail();
});
static::updated(function (self $model) {
$user = auth()->user();
if (!$user instanceof \App\Models\User) {
$user = null;
}
if (isset($model->getChanges()['brand_id'])) {
event(new ClaimModelChanged(
$model->load('brand'),
'brand',
Str::singular(trans('models.classes.brands')),
$user,
));
}
if (isset($model->getChanges()['subject_id'])) {
event(new ClaimModelChanged(
$model->load('claimSubject'),
'claimSubject',
trans('models.classes.claimsubjects'),
$user,
));
}
if (isset($model->getChanges()['status'])) {
event(new ClaimModelChanged(
$model,
'status',
trans('validation.custom.status'),
$user,
));
}
if (isset($model->getChanges()['type'])) {
event(new ClaimModelChanged(
$model,
'type',
trans('validation.custom.type'),
$user,
));
}
if (
isset($model->getChanges()['response_type'])
&& !$model->response_type->equals(ClaimResponseType::manual)
) {
event(new ClaimModelChanged(
$model,
'response_type',
trans('validation.custom.response_type'),
$user,
));
}
});
}
// * RELATIONS
/**
* Brand belongs to relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function brand(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Brand::class);
}
/**
* ClaimSubject subject belongs to relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function claimSubject(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(ClaimSubject::class, 'subject_id');
}
/**
* ClaimMessage has many relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function claimMessages(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(ClaimMessage::class);
}
// * METHODS
/**
* Convert the integer to base 36 and make uppercase.
*
* @param integer $int
* @return string
*/
public static function encodeIntegerToBase36(int $int): string
{
return strtoupper(base_convert($int, 10, 36));
}
/**
* Convert back to base 10 from base 36, case insensitive.
*
* @param string $str
* @return string
*/
public static function decodeBase36ToInteger(string $str): string
{
return base_convert(strtolower($str), 36, 10);
}
/**
* Get formated address.
*
* @return string
*/
public function getFormatedAddress(): string
{
return implode(', ', array_filter([
$this->address,
trim(implode(' ', array_filter([$this->postcode, $this->city])))
]));
}
/**
* Get the formmated csv line for the current model.
*
* @return array
*/
public function getFormattedCsvLine(): array
{
return [
$this->reference,
$this->created_at->toDateTimeString(),
sprintf('%s %s', $this->first_name, Str::upper($this->last_name)),
$this->email,
sprintf('%s, %s, %s', $this->address, $this->postcode, $this->city),
$this->status->label(),
$this->claimSubject->label,
$this->type->label(),
$this->brand->name,
$this->message,
$this->export_file_name,
];
}
/**
* Get the csv headers for this model.
*
* @return array
*/
public static function getCsvHeaders(): array
{
return [
'Référence',
'Date de création',
'Prénom NOM',
'Email',
'Adresse',
'Statut',
'Sujet',
'Type',
'Marque',
'Message',
'Pièce jointe',
];
}
// * VIRTUAL ATTRIBUTES
/**
* 'file_extension' virtual property.
*
* @return string
*/
public function getFileExtensionAttribute(): string
{
return File::extension($this->file);
}
/**
* 'export_file_name' virtual property.
*
* @return string
*/
public function getExportFileNameAttribute(): string
{
return $this->file ?
sprintf(
'%s.%s',
$this->reference,
$this->file_extension,
) :
__('Aucune pièce jointe');
}
}