290 lines
9 KiB
PHP
290 lines
9 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\DepartaimantCollectionType;
|
|
use App\Exceptions\CrmException;
|
|
use App\Http\Resources\CustomerCrmResource;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Notifications\Notifiable;
|
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class Customers extends Authenticatable
|
|
{
|
|
use Notifiable;
|
|
|
|
protected $fillable = [
|
|
'email',
|
|
'username'
|
|
];
|
|
|
|
protected $guard = 'customer';
|
|
|
|
public function recipes()
|
|
{
|
|
return $this->belongsToMany(Recipes::class, 'customers_recipes', 'customer_id', 'recipe_id');
|
|
}
|
|
|
|
public function products()
|
|
{
|
|
return $this->belongsToMany(Products::class, 'cart', 'customer_id', 'product_id');
|
|
}
|
|
|
|
public function messages()
|
|
{
|
|
return $this->hasMany(Message::class, 'to');
|
|
}
|
|
|
|
public function sentMessages()
|
|
{
|
|
return $this->hasMany(Message::class, 'from');
|
|
}
|
|
|
|
/**
|
|
* Get conversations with messages sorted by time
|
|
*
|
|
* @return array
|
|
*/
|
|
public function conversations(): array
|
|
{
|
|
$dateSort = function ($a, $b) {
|
|
return Carbon::parse(
|
|
$a->getRawOriginal('created_at')
|
|
)->timestamp < Carbon::parse($b->getRawOriginal('created_at'))->timestamp;
|
|
};
|
|
$messageFilter = function ($item) {
|
|
return $item->all();
|
|
};
|
|
$messageWith = [
|
|
'fromCustomer' => function ($q) {
|
|
$q->select(['id', 'username', 'created_at']);
|
|
},
|
|
'toCustomer' => function ($q) {
|
|
$q->select(['id', 'username', 'created_at']);
|
|
}
|
|
];
|
|
/**
|
|
* Hack workaround https://github.com/livewire/livewire/issues/1054
|
|
*/
|
|
/** @var \Illuminate\Support\Collection $sentM */
|
|
$sentM = $this->sentMessages()
|
|
->where('hide_from', false)
|
|
->with($messageWith)->get()
|
|
->groupBy('toCustomer.username')->map($messageFilter);
|
|
/** @var \Illuminate\Support\Collection $receivedM */
|
|
$receivedM = $this->messages()
|
|
->where('hide_to', false)->with($messageWith)->get()
|
|
->groupBy('fromCustomer.username')->map($messageFilter);
|
|
|
|
$output = $receivedM->mapWithKeys(function ($messagesArray, $fromUsername) use (&$sentM, $dateSort) {
|
|
$responses = collect(\array_merge($sentM->pull($fromUsername) ?? [], $messagesArray))->sort($dateSort);
|
|
$last = $responses->first();
|
|
return [$fromUsername => [
|
|
'to' => $fromUsername,
|
|
'to_id' => collect($messagesArray)->first()->fromCustomer->id,
|
|
'id' => $last->id,
|
|
'date' => $last->created_at,
|
|
'dateRaw' => $last->getRawOriginal('created_at'),
|
|
'preview' => Str::limit($last->message, 15),
|
|
'messages' => $responses->values()->all()
|
|
]];
|
|
});
|
|
// map sur les message envoyés (qui n'ont pas encore eu de réponses)
|
|
$outputSentM = $sentM->mapWithKeys(function ($messagesArray) {
|
|
$sent = collect($messagesArray);
|
|
$last = $sent->first();
|
|
$toCustomer = $last->toCustomer;
|
|
$toUserName = $toCustomer->username;
|
|
return [$toUserName => [
|
|
'to' => $toUserName,
|
|
'to_id' => $toCustomer->id,
|
|
'id' => $last->id,
|
|
'date' => $last->created_at,
|
|
'dateRaw' => $last->getRawOriginal('created_at'),
|
|
'preview' => Str::limit($last->message, 15),
|
|
'messages' => $sent->values()->all()
|
|
]];
|
|
});
|
|
return $output->merge($outputSentM)->sort(function ($a, $b) {
|
|
return Carbon::parse(
|
|
$a['dateRaw']
|
|
)->timestamp < Carbon::parse($b['dateRaw'])->timestamp;
|
|
})->toArray();
|
|
}
|
|
|
|
public function notifications()
|
|
{
|
|
return $this->belongsToMany(Notifications::class);
|
|
}
|
|
|
|
public function getAllNotifications()
|
|
{
|
|
return Notifications::where('customer_id', $this->id)
|
|
->orWhere('customer_id', null)
|
|
->with('notifiable')
|
|
->orderBy('created_at', 'DESC')
|
|
->get();
|
|
}
|
|
|
|
public function readNotifications()
|
|
{
|
|
return $this->belongsToMany(Notifications::class, 'notifications_read', 'customer_id', 'notification_id');
|
|
}
|
|
|
|
public function surveysAnswers()
|
|
{
|
|
return $this->belongsToMany(
|
|
SurveysAnswers::class,
|
|
'surveys_answer_customer',
|
|
'customer_id',
|
|
'surveys_answer_id'
|
|
);
|
|
}
|
|
|
|
public function departaimantsCollections()
|
|
{
|
|
return $this->hasMany(DepartaimantsCollection::class, 'customer_id');
|
|
}
|
|
|
|
/**
|
|
* Get all user Departaimant collection or create them if they dont exists
|
|
*
|
|
* @return \Illuminate\Support\Collection
|
|
*/
|
|
public function getOrCreateAllDepartaimentsCollections(): Collection
|
|
{
|
|
/** @var \Illuminate\Database\Eloquent\Collection $collections */
|
|
$collections = $this->departaimantsCollections->keyBy('type');
|
|
/** @var \App\Enums\DepartaimantCollectionType $depColection */
|
|
foreach (DepartaimantCollectionType::toArray() as $depColectionType) {
|
|
if (!$collections->has($depColectionType->value)) {
|
|
$depCollection = new DepartaimantsCollection([
|
|
'type' => $depColectionType->value
|
|
]);
|
|
$depCollection->customer()->associate($this);
|
|
$depCollection->save();
|
|
$collections->add($depCollection);
|
|
}
|
|
}
|
|
return $collections;
|
|
}
|
|
|
|
/**
|
|
* Check if Customer has a recipe in favorites
|
|
*
|
|
* @param Recipes $recipe
|
|
* @return boolean
|
|
*/
|
|
public function hasRecipe(Recipes $recipe)
|
|
{
|
|
return $this->recipes()->find($recipe) ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Set the rating for this customer
|
|
*
|
|
* @param Recipes $recipe
|
|
* @return float|null
|
|
*/
|
|
public function getRecipeRating(Recipes $recipe)
|
|
{
|
|
$recipe = $this->recipes()->withPivot('rating')->find($recipe);
|
|
return $recipe->pivot->rating ?? null;
|
|
}
|
|
|
|
/**
|
|
* Set the rating for this customer
|
|
*
|
|
* @param Recipes $recipe
|
|
* @param float $rating
|
|
* @return bool
|
|
*/
|
|
public function setRecipeRating(Recipes $recipe, float $rating)
|
|
{
|
|
/** @var \Illuminate\Database\Eloquent\Relations\Pivot $p */
|
|
$p = $this->recipes()->find($recipe);
|
|
if (!$p) {
|
|
return (bool)count($this->recipes()->syncWithoutDetaching([$recipe->id => ['rating' => $rating]]));
|
|
} else {
|
|
$p->pivot->rating = $rating;
|
|
return $p->save();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the crm Data of a customer
|
|
*
|
|
* @throws CrmException
|
|
* @return object crm user
|
|
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
|
*/
|
|
public function getApiDataAttribute()
|
|
{
|
|
/** @var \App\Lib\LDCCRM\ApiV1 */
|
|
$crm = app('crmApi');
|
|
$response = (object)$crm->getCustomer($this->crm_id);
|
|
switch ($response->status) {
|
|
case 'KO':
|
|
throw new CrmException(sprintf('Api call error %s', $response->message));
|
|
case 'OK':
|
|
return $response->user;
|
|
default:
|
|
throw new CrmException('Unknown status');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the crm Data of a customer
|
|
*
|
|
* @throws CrmException
|
|
* @return object crm user
|
|
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
|
*/
|
|
public function updateApiData(CustomerCrmResource $resource)
|
|
{
|
|
/** @var \App\Lib\LDCCRM\ApiV1 */
|
|
$crm = app('crmApi');
|
|
$response = (object)\call_user_func_array([$crm, 'updateCustomer'], $resource->toArray(null));
|
|
switch ($response->status) {
|
|
case 'KO':
|
|
throw new CrmException(sprintf('Api call error %s', $response->message));
|
|
case 'OK':
|
|
return $response->user;
|
|
default:
|
|
throw new CrmException('Unknown status');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This mutate Customer attributes to array
|
|
* including only non critical properties and crm values
|
|
* (One that can be send to front office without security breach)
|
|
*
|
|
* @return array
|
|
*/
|
|
public function toArray()
|
|
{
|
|
if ($this->crm_id) {
|
|
return collect(array_merge(
|
|
parent::toArray(),
|
|
(array)$this->apiData
|
|
))->intersectByKeys([
|
|
'email' => '',
|
|
'firstname' => '',
|
|
'lastname' => '',
|
|
'address' => '',
|
|
'address2' => '',
|
|
'postcode' => '',
|
|
'birth_date' => '',
|
|
'city' => '',
|
|
'country' => '',
|
|
'opt_in' => '',
|
|
'phone' => ''
|
|
])->toArray();
|
|
} else {
|
|
return parent::toArray();
|
|
}
|
|
}
|
|
}
|