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)->toBase(); /** @var \Illuminate\Support\Collection $receivedM */ $receivedM = $this->messages() ->where('hide_to', false)->with($messageWith)->get() ->groupBy('fromCustomer.username')->map($messageFilter)->toBase(); $output = $receivedM->mapWithKeys(function ($messagesArray, $fromUsername) use (&$sentM, $dateSort) { $responses = collect(\array_merge($sentM->pull($fromUsername) ?? [], $messagesArray))->sort($dateSort); $last = $responses->last(); return [$fromUsername => collect([ '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() ])]; })->toBase(); // * 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->last(); $toCustomer = $last->toCustomer; $toUserName = $toCustomer->username; return [$toUserName => collect([ '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() ])]; })->toBase(); 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 boolean */ public function setRecipeRating(Recipes $recipe, float $rating) { /** @var \Illuminate\Database\Eloquent\Relations\Pivot $p */ $p = $this->recipes()->withPivot('rating')->find($recipe); if (!$p) { return (bool)count($this->recipes()->syncWithoutDetaching([$recipe->id => ['rating' => $rating]])); } else { $p->pivot->rating = $rating; return $p->pivot->saveOrFail(); } } /** * Get the crm Data of a customer * * @throws CrmException * @return \LDC\LDCCRM\Models\Customer * @author Jérémy Munsch * @throws \LDC\LDCCRM\Exceptions\CrmException if cannot fetch data from crm */ public function getApiDataAttribute(): CrmCustomer { /** @var \LDC\LDCCRM\CrmApiV2 */ $crm = app('crmAPI'); $crmCustomer = $crm->getCustomer($this->hashcode); if (!$crmCustomer) { throw new CrmException('CRM get Customer returned null'); } return $crmCustomer; } /** * Set the crm Data of a customer * * @throws CrmException * @return object crm user * @author Jérémy Munsch * * @throws \LDC\LDCCRM\Exceptions\CrmException * if an error occurs on server side or on getting response * @throws \LDC\LDCCRM\Exceptions\ApiErrorException * If any error or \LDC\LDCCRM\Enums\ApiError occurs */ public function updateApiData(CustomerCrmResource $resource): CrmCustomer { $data = $resource->toArray(null); /** @var \LDC\LDCCRM\CrmApiV2 */ $crm = app('crmAPI'); $crmCustomer = $crm->getCustomer($data['hashcode']); if (!$crmCustomer) { throw new CrmException('CRM get Customer returned null'); } $crmCustomer->fill($data); $crmCustomer->save(); return $crmCustomer; } /** * 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(); } } }