ldc-jeusselin/app/Models/Customer.php

303 lines
9.6 KiB
PHP

<?php
namespace App\Models;
use App\Enums\CustomerTypeEnum;
use App\Http\Resources\CustomerCrmResource;
use App\Notifications\Customer\ResetPassword as NotificationResetPassword;
use App\Notifications\Customer\VerifyEmail as NotificationVerifyEmail;
use Illuminate\Contracts\Auth\CanResetPassword;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Validation\ValidationException;
use LDC\LDCCRM\Enums\ApiError;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Exceptions\CrmException;
use LDC\LDCCRM\Models\Customer as CrmCustomer;
/**
* @property string $crm_hashcode
* @property string $firstname
* @property string $lastname
* @property string $email
* @property string $client_number
* @property string $social_denomination
* @property string $tech_commercial
* @property integer $tc_id
* @property string $siret
* @property string $numtva
* @property string $certiphyto
* @property \Carbon\Carbon $certiphyto_date
* @property boolean $eleveur_volailles
* @property boolean $eleveur_porcs
* @property boolean $eleveur_bovins
* @property string $capacite_stockage
* @property string $temps_chargement
* @property boolean $stockage_aplat
* @property boolean $stockage_cellule
* @property string $adress_chargement
* @property string $optional_contact
* @property \Carbon\Carbon $ok_cgv
* @property string $email_verify_token
* @property boolean $email_verified
* @property string $password_token
* @property \App\Enums\CustomerTypeEnum $role
* @property string $remember_token
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*
* @property-read \LDC\LDCCRM\Models\Customer $api_data
* @property-read boolean $is_validated_pro
*
* @package App\Models
*/
class Customer extends Authenticatable implements MustVerifyEmail, CanResetPassword
{
use HasFactory;
use Notifiable;
/** @var \LDC\LDCCRM\Models\Customer|null */
private $crmCustomer;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'hashcode',
'firstname',
'lastname',
'email',
'client_number',
'social_denomination',
'tech_commercial',
'siret',
'numtva',
'certiphyto',
'certiphyto_date',
'eleveur_volailles',
'eleveur_porcs',
'eleveur_bovins',
'capacite_stockage',
'temps_chargement',
'stockage_aplat',
'stockage_cellule',
'adress_chargement',
'optional_contact',
'ok_cgv',
'email_verify_token',
'email_verified',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'certiphyto_date' => 'datetime',
'ok_cgv' => 'boolean',
'last_connection' => 'datetime',
'email_verified_at' => 'datetime',
'role' => CustomerTypeEnum::class
];
// * --- AUTH ---
/**
* Send the email verification notification.
*
* @return void
*/
public function sendEmailVerificationNotification()
{
$this->deleteIfDoesNotExistsInCrm();
$this->notify(new NotificationVerifyEmail());
}
/**
* Mark the given user's email as verified.
*
* @return boolean
* @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.
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public function markEmailAsVerified()
{
$this->deleteIfDoesNotExistsInCrm();
try {
$result = $this->api_data->activate() && parent::markEmailAsVerified();
if ($result) {
\session()->flash('success', \trans('Votre compe est activé'));
}
return $result;
} catch (ApiErrorException $e) {
if ($e->getApiError()->equals(ApiError::customerAlreadyActive)) {
return true && parent::markEmailAsVerified();
}
throw $e;
}
}
/**
* Send the password reset notification.
*
* @param mixed $token
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->deleteIfDoesNotExistsInCrm();
/** @var string $token */
$this->notify(new NotificationResetPassword($token));
}
/**
* Check if the customer exists in CRM.
*
* @return boolean
*/
public function existsInCrm(): bool
{
return $this->hashcode and CrmCustomer::find($this->hashcode);
}
/**
* Force delete and logout if is logged in case the customer
* does not exists in CRM.
*
* @return void
* @throws \Illuminate\Validation\ValidationException If the account is deleted because does not exists in CRM.
*/
private function deleteIfDoesNotExistsInCrm(): void
{
if ($this->existsInCrm()) {
return;
}
/** @var static|null $loggedCustomer */
$loggedCustomer = \auth('frontend')->user();
$isLogged = \optional($loggedCustomer)->id === $this->id and !\is_null($this->id);
if ($isLogged) {
\auth('frontend')->logout();
}
$this->forceDelete();
throw ValidationException::withMessages([
'error' => trans('Le compte \'existe pas.')
]);
}
// * --- END AUTH ---
/**
* Getter is_validated_pro attribute
*
* @return boolean
*/
public function getIsValidatedProAttribute(): bool
{
return $this->role->equals(CustomerTypeEnum::professional) and !empty($this->client_number);
}
/**
* Get the crm Data of a customer
*
* @return \LDC\LDCCRM\Models\Customer
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
* @throws \LDC\LDCCRM\Exceptions\CrmException If cannot fetch data from crm.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are :
* - modelNotFound, If this customer hashcode could not be found.
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public function getApiDataAttribute(): CrmCustomer
{
// phpcs:enable
if (!$this->crmCustomer) {
/** @var \LDC\LDCCRM\CrmApiV4 */
$crm = app('crmAPI');
$this->crmCustomer = $crm->getCustomer(\strval($this->hashcode));
if (!$this->crmCustomer) {
throw new CrmException('CRM get Customer returned null');
}
}
return $this->crmCustomer;
}
/**
* Set the crm Data of a customer
*
* @param \App\Http\Resources\CustomerCrmResource $resource
* @return \LDC\LDCCRM\Models\Customer crm user
*
* @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.
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public function updateApiData(CustomerCrmResource $resource): CrmCustomer
{
// phpcs:enable
$data = $resource->toArray(null);
if (!$this->crmCustomer) {
/** @var \LDC\LDCCRM\CrmApiV4 */
$crm = app('crmAPI');
$this->crmCustomer = $crm->getCustomer(\strval($this->hashcode));
if (!$this->crmCustomer) {
throw new CrmException('CRM get Customer returned null');
}
}
$this->crmCustomer->fill($data);
$this->crmCustomer->save();
return $this->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->hashcode) {
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();
}
}
}