ldc-boutique-cnc-sable/app/Services/CustomerRegistrationService.php
Jérémy Munsch 2aa4fa8aed
feat(crm): implement unsubscribe from newsletter functionality
- Added UnsubscribeFromNewsletter action and input/output classes.
- Introduced CrmHashcode value object and its cast.
- Updated NewsletterController to use the new unsubscribe action.
- Enhanced validation in UnsubscribeNewsletterRequest.
2026-10-27 09:58:34 +01:00

127 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services;
use App\Contracts\Repositories\EmployeeRepository;
use App\Exceptions\Crm\CrmCustomerExistsException;
use App\Exceptions\CrmServiceException;
use App\Models\Customer;
use Domain\Enums\Country;
use Domain\Models\ValueObjects\Code;
use Domain\Models\ValueObjects\CrmCustomer;
use Domain\Models\ValueObjects\Email;
use Domain\Models\ValueObjects\Matricule;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Infrastructure\Adapters\Services\AppCustomerAuthService;
use Ramsey\Uuid\Uuid;
use Shared\ValueObjects\CrmHashcode;
use UnexpectedValueException;
class CustomerRegistrationService
{
public function __construct(
private readonly AppCustomerAuthService $authService,
private readonly CrmService $crmService,
private readonly EmployeeRepository $employeeRepository
) {
}
/**
* @param array{
* matricule:string,
* code:string,
* lastname:string,
* firstname:string,
* phone:string|null,
* address:string|null,
* postal_code:string,
* city:string,
* email:string,
* password:string,
* optin:bool,
* birth_date:\DateTimeImmutable
* } $data
*
* @throws ValidationException
* @throws UnexpectedValueException
*/
public function registerCustomer(array $data): void
{
DB::transaction(function () use ($data) {
$requestMatricule = $data['matricule'];
$requestCode = $data['code'];
// * Persist and associate Customer + Salarie
$customer = new Customer([
'email' => new Email($data['email']),
]);
// * Temp hashcode to satisfy constraint
$customer->hashcode = new CrmHashcode(Uuid::uuid4());
$customer->saveOrFail();
$employee = $this->employeeRepository
->findByMatriculeAndCode(
new Matricule($requestMatricule),
new Code($requestCode)
);
if (! $employee) {
throw new ModelNotFoundException('Employee not found');
}
$employee->customer()->associate($customer);
$employee->saveOrFail();
$phone = Arr::get($data, 'phone');
$address = Arr::get($data, 'address');
$crmCustomer = new CrmCustomer(
hashcode: null,
email: Arr::string($data, 'email'),
password: Arr::string($data, 'password'),
firstname: Arr::string($data, 'firstname'),
lastname: Arr::string($data, 'lastname'),
birthDate: $data['birth_date']->format('Y-m-d'),
phone: is_string($phone) ? $phone : null,
address: is_string($address) ? $address : null,
address2: null,
city: Arr::string($data, 'city'),
postcode: Arr::string($data, 'postal_code'),
country: Country::france,
optIn: Arr::boolean($data, 'optin'),
status: false,
lastConnection: null,
);
try {
$result = $this->crmService->persist($crmCustomer);
if (! $result->hashcode) {
throw new UnexpectedValueException(
'CRM did not return a hashcode for the created customer'
);
}
$customer->hashcode = new CrmHashcode(Uuid::uuid4());
$customer->saveOrFail();
$customer->sendEmailVerificationNotification();
$this->authService->logIn($customer);
} catch (CrmCustomerExistsException $e) {
throw ValidationException::withMessages([
'error' => trans('An account is already associated with this email address'),
]);
} catch (CrmServiceException $e) {
report($e);
throw ValidationException::withMessages([
'error' => trans('An error has occurred. Please try again later'),
]);
}
});
}
}