From e618e6fb4683d3375c0e4d86cdc5277fc35b4f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 23 Aug 2021 20:20:51 +0200 Subject: [PATCH] Customer::info and Customer::login try to get loaded relations first --- .../Controllers/Api/V2/ArcadiaController.php | 2 +- .../Controllers/Api/V2/CustomerController.php | 16 ++--- .../Resources/Api/V2/CustomerResource.php | 4 +- app/Models/Customer.php | 66 +++++++++++++++++-- app/Policies/CustomerPolicy.php | 2 +- tests/Feature/ApiV2/ApiBase.php | 2 +- tests/Feature/ApiV2/CustomerTest.php | 4 +- tests/Unit/CrmClientTester.php | 2 +- tests/Unit/CrmClientV2CustomerTest.php | 2 +- 9 files changed, 79 insertions(+), 21 deletions(-) diff --git a/app/Http/Controllers/Api/V2/ArcadiaController.php b/app/Http/Controllers/Api/V2/ArcadiaController.php index a30ba1f..ca3c0bd 100644 --- a/app/Http/Controllers/Api/V2/ArcadiaController.php +++ b/app/Http/Controllers/Api/V2/ArcadiaController.php @@ -54,7 +54,7 @@ class ArcadiaController extends Controller $xml = 'none'; try { /** @var \App\Models\CustomerInfo $customerInfo */ - $customerInfo = $customer->info($service->brand)->firstOrFail(); + $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL); $orderType = ArcadiaOrderType::make(intval($request->state_order)); $xml = $this->makeXml($request, $type, $orderType, $customer, $customerInfo); diff --git a/app/Http/Controllers/Api/V2/CustomerController.php b/app/Http/Controllers/Api/V2/CustomerController.php index f855456..62dbefb 100644 --- a/app/Http/Controllers/Api/V2/CustomerController.php +++ b/app/Http/Controllers/Api/V2/CustomerController.php @@ -45,7 +45,7 @@ class CustomerController extends Controller } /** @var \App\Models\CustomerInfo */ - $customerInfo = $customer->info($service->brand)->firstOrNew(); + $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_NEW); if ($customerInfo->id) { throw new ApiErrorException(ApiError::customerExists()); } @@ -55,7 +55,7 @@ class CustomerController extends Controller $customerInfo->saveOrFail(); /** @var \App\Models\CustomerLogin */ - $customerLogin = $customer->login($service->brand)->firstOrNew(); + $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_NEW); $customerLogin->fill($request->validated()); $customerLogin->brand()->associate($service->brand); $customerLogin->customer()->associate($customer); @@ -98,12 +98,12 @@ class CustomerController extends Controller } /** @var \App\Models\CustomerInfo */ - $customerInfo = $customer->info($service->brand)->firstOrFail(); + $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL); $customerInfo->fill($request->validated()); $customerInfo->saveOrFail(); /** @var \App\Models\CustomerLogin */ - $customerLogin = $customer->login($service->brand)->firstOrFail(); + $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL); $customerLogin->fill($request->validated()); $customerLogin->saveOrFail(); @@ -123,9 +123,9 @@ class CustomerController extends Controller // TODO : A voir pour les stats, obuton dans le bo qui permet de faire les stats sur les customer puis supprimer // TODO : Gestion avec mesBR /** @var \App\Models\CustomerInfo */ - $customerInfo = $customer->info($service->brand)->firstOrFail(); + $customerInfo = $customer->info($service->brand, Customer::FIRST_OR_FAIL); /** @var \App\Models\CustomerLogin */ - $customerLogin = $customer->login($service->brand)->firstOrFail(); + $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL); if ( !$customerInfo->delete() || @@ -170,7 +170,7 @@ class CustomerController extends Controller /** @var \App\Models\Customer */ $customer = Customer::where('email', $request->email)->firstOrFail(); /** @var \App\Models\CustomerLogin */ - $customerLogin = $customer->login($service->brand)->firstOrFail(); + $customerLogin = $customer->login($service->brand, Customer::FIRST_OR_FAIL); if (!$customerLogin->passwordMatch($request->password)) { throw new ApiErrorException(ApiError::authFailed()); @@ -198,7 +198,7 @@ class CustomerController extends Controller public function activateAccount(Customer $customer, Service $service) { $this->authorize('customerBelongsToService', $customer); - $login = $customer->login($service->brand)->firstOrFail(); + $login = $customer->login($service->brand, Customer::FIRST_OR_FAIL); if ($login->status === 0) { $login->status = 1; diff --git a/app/Http/Resources/Api/V2/CustomerResource.php b/app/Http/Resources/Api/V2/CustomerResource.php index 243caca..da2a64a 100644 --- a/app/Http/Resources/Api/V2/CustomerResource.php +++ b/app/Http/Resources/Api/V2/CustomerResource.php @@ -38,8 +38,8 @@ class CustomerResource extends JsonResource public function __construct(Brand $brand, Customer $customer) { $this->customer = $customer; - $this->info = $customer->info($brand)->firstOrFail(); - $this->login = $customer->login($brand)->firstOrFail(); + $this->info = $customer->info($brand, Customer::FIRST_OR_FAIL); + $this->login = $customer->login($brand, Customer::FIRST_OR_FAIL); } /** diff --git a/app/Models/Customer.php b/app/Models/Customer.php index f490958..87ad021 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -11,6 +11,10 @@ class Customer extends Model { use HasFactory; + public const FIRST_OR_NULL = 0; + public const FIRST_OR_NEW = 1; + public const FIRST_OR_FAIL = 2; + protected $fillable = [ 'email' ]; @@ -27,17 +31,35 @@ class Customer extends Model /** * Get the CustomerInfo from a specific brand + * or create a New one if $firstOrNewOrFail is 1 + * throw model not found exception if firstOrNewOrFail = 2 * * @param Brand $brand + * @param int $firstOrNewOrFail * @return \Illuminate\Database\Eloquent\Builder */ - public function info(Brand $brand) + public function info(Brand $brand, $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerInfo { - return CustomerInfo::whereHas('brand', function (Builder $query) use ($brand) { + if (isset($this->relations['infos'])) { + /** @var \App\Models\CustomerInfo $info */ + foreach ($this->relations['infos'] as $info) { + if ($info->brand_id === $brand->id) { + return $info; + } + } + } + $query = CustomerInfo::whereHas('brand', function (Builder $query) use ($brand) { $query->where('id', $brand->id); })->whereHas('customer', function (Builder $query) use ($brand) { $query->where('id', $this->id); }); + if ($firstOrNewOrFail === self::FIRST_OR_NEW) { + return $query->firstOrNew(); + } + if ($firstOrNewOrFail === self::FIRST_OR_FAIL) { + return $query->firstOrFail(); + } + return $query->first(); } /** @@ -52,17 +74,53 @@ class Customer extends Model /** * Get the CustomerLogin from a specific brand + * or create a New one if $firstOrNewOrFail is 1 + * throw model not found exception if firstOrNewOrFail = 2 * * @param Brand $brand + * @param int $firstOrNewOrFail * @return \Illuminate\Database\Eloquent\Builder */ - public function login(Brand $brand) + public function login(Brand $brand, $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerLogin { - return CustomerLogin::whereHas('brand', function (Builder $query) use ($brand) { + if (isset($this->relations['logins'])) { + /** @var \App\Models\CustomerLogin $login */ + foreach ($this->relations['logins'] as $login) { + if ($login->brand_id === $brand->id) { + return $login; + } + } + } + $query = CustomerLogin::whereHas('brand', function (Builder $query) use ($brand) { $query->where('id', $brand->id); })->whereHas('customer', function (Builder $query) use ($brand) { $query->where('id', $this->id); }); + if ($firstOrNewOrFail === self::FIRST_OR_NEW) { + return $query->firstOrNew(); + } + if ($firstOrNewOrFail === self::FIRST_OR_FAIL) { + return $query->firstOrFail(); + } + return $query->first(); + } + + /** + * Load login and brand for this customer + * + * @param Brand $brand + * @return self + */ + public function loadBrandData(Brand $brand): self + { + return $this->load([ + 'logins' => function ($q) use ($brand) { + $q->where('brand_id', $brand->id); + }, + 'infos' => function ($q) use ($brand) { + $q->where('brand_id', $brand->id); + } + ]); } /** diff --git a/app/Policies/CustomerPolicy.php b/app/Policies/CustomerPolicy.php index e9253b2..32e33ee 100644 --- a/app/Policies/CustomerPolicy.php +++ b/app/Policies/CustomerPolicy.php @@ -12,6 +12,6 @@ class CustomerPolicy public function customerBelongsToService(Service $service, Customer $customer) { - return $customer->login($service->brand)->exists(); + return !\is_null($customer->login($service->brand)); } } diff --git a/tests/Feature/ApiV2/ApiBase.php b/tests/Feature/ApiV2/ApiBase.php index a01c1cc..0303a08 100644 --- a/tests/Feature/ApiV2/ApiBase.php +++ b/tests/Feature/ApiV2/ApiBase.php @@ -94,7 +94,7 @@ class ApiBase extends BaseTestCase $service->bearer_pwd = $bearer_pwd; // get customer info - $info = $customer->info($brand)->firstOrFail(); + $info = $customer->info($brand, Customer::FIRST_OR_FAIL); return compact('customer', 'service', 'login', 'brand', 'info'); } diff --git a/tests/Feature/ApiV2/CustomerTest.php b/tests/Feature/ApiV2/CustomerTest.php index 2fc930a..bf144b4 100644 --- a/tests/Feature/ApiV2/CustomerTest.php +++ b/tests/Feature/ApiV2/CustomerTest.php @@ -29,8 +29,8 @@ class CustomerTest extends ApiBase $this->assertInstanceOf(Collection::class, $logins); $this->assertInstanceOf(Collection::class, $brands); $this->assertInstanceOf(Collection::class, $optInHistory); - $this->assertInstanceOf(CustomerInfo::class, $customer->info($brands->first())->first()); - $this->assertInstanceOf(CustomerLogin::class, $customer->login($brands->first())->first()); + $this->assertInstanceOf(CustomerInfo::class, $customer->info($brands->first())); + $this->assertInstanceOf(CustomerLogin::class, $customer->login($brands->first())); } /** diff --git a/tests/Unit/CrmClientTester.php b/tests/Unit/CrmClientTester.php index f76d422..6059a01 100644 --- a/tests/Unit/CrmClientTester.php +++ b/tests/Unit/CrmClientTester.php @@ -59,7 +59,7 @@ abstract class CrmClientTester extends TestCase $service = $brand->services()->firstOrFail(); // get customer info - $info = $customer->info($brand)->firstOrFail(); + $info = $customer->info($brand, Customer::FIRST_OR_FAIL); // regen bearer token to get the pwd in clear $bearer_token = $service->generateBearerToken(); diff --git a/tests/Unit/CrmClientV2CustomerTest.php b/tests/Unit/CrmClientV2CustomerTest.php index 4ed021a..9af2328 100644 --- a/tests/Unit/CrmClientV2CustomerTest.php +++ b/tests/Unit/CrmClientV2CustomerTest.php @@ -133,7 +133,7 @@ class CrmClientV2CustomerTest extends CrmClientTester /** @var \App\Models\Brand */ $brand = $login->brand; /** @var \App\Models\CustomerInfo */ - $info = $customer->info($brand)->firstOrFail(); + $info = $customer->info($brand, ModelsCustomer::FIRST_OR_FAIL); $api = new CrmApiV2(); $customer = $api->getCustomerOrNew($info->hashcode);