2026-08-24 21:06:11 +03:00
|
|
|
<?php
|
|
|
|
|
|
2026-09-16 13:44:14 +03:00
|
|
|
namespace Modules\Core\Customer\Privacy;
|
2026-08-24 21:06:11 +03:00
|
|
|
|
|
|
|
|
use Lunar\Models\Customer;
|
|
|
|
|
use Modules\Core\Privacy\Contracts\PersonalDataProvider;
|
2026-09-16 01:21:22 +03:00
|
|
|
use Modules\Core\Privacy\DTOs\CustomerSubject;
|
|
|
|
|
use Modules\Core\Privacy\Enums\ErasureOutcome;
|
|
|
|
|
use Modules\Core\Privacy\DTOs\ProviderErasureResult;
|
|
|
|
|
use Modules\Core\Privacy\DTOs\ProviderExportResult;
|
|
|
|
|
use Modules\Core\Privacy\DTOs\UserSubject;
|
2026-08-24 21:06:11 +03:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The Customer record itself (lunar_customers) and, on the User side, the User's
|
|
|
|
|
* own name/email. This is the one provider that implements both scopes
|
|
|
|
|
* meaningfully, and they are deliberately kept from touching each other's data:
|
|
|
|
|
*
|
|
|
|
|
* - eraseForCustomer() clears the account's own fields (name, company, tax id)
|
|
|
|
|
* only — it never touches any linked User's login or identity, even though
|
|
|
|
|
* $customer->users exists. Erasing a business account must not destroy the
|
|
|
|
|
* login access of every person who works there.
|
|
|
|
|
* - eraseForUser() clears that one person's name/email only — it never touches
|
|
|
|
|
* the Customer record's own fields, and it also detaches the User from every
|
|
|
|
|
* Customer they're linked to (the customer_user pivot — see docs/modules.md
|
|
|
|
|
* "Customer/User Pairing"), since erasing a person's identity should end
|
|
|
|
|
* their membership everywhere, without erasing the business accounts
|
|
|
|
|
* themselves or any other User still linked to them.
|
|
|
|
|
*
|
|
|
|
|
* No legal retention requirement applies to this table on its own, so both
|
|
|
|
|
* directions are freely erased — Order/OrderAddress, which DO have a retention
|
|
|
|
|
* requirement, are handled separately by OrderDataProvider.
|
|
|
|
|
*/
|
|
|
|
|
class CustomerDataProvider implements PersonalDataProvider
|
|
|
|
|
{
|
|
|
|
|
public function name(): string
|
|
|
|
|
{
|
|
|
|
|
return 'customer';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function exportForCustomer(CustomerSubject $subject): ProviderExportResult
|
|
|
|
|
{
|
|
|
|
|
$customer = Customer::find($subject->customerId);
|
|
|
|
|
|
|
|
|
|
return new ProviderExportResult('customer', $customer ? [
|
|
|
|
|
'id' => $customer->id,
|
|
|
|
|
'title' => $customer->title,
|
|
|
|
|
'first_name' => $customer->first_name,
|
|
|
|
|
'last_name' => $customer->last_name,
|
|
|
|
|
'company_name' => $customer->company_name,
|
|
|
|
|
'tax_identifier' => $customer->tax_identifier,
|
|
|
|
|
'meta' => $customer->meta,
|
|
|
|
|
'users' => $customer->users->map(fn ($user) => [
|
|
|
|
|
'id' => $user->id,
|
|
|
|
|
'name' => $user->name,
|
|
|
|
|
'email' => $user->email,
|
|
|
|
|
])->all(),
|
|
|
|
|
] : []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function exportForUser(UserSubject $subject): ProviderExportResult
|
|
|
|
|
{
|
|
|
|
|
$model = config('auth.providers.users.model');
|
|
|
|
|
$user = $model::find($subject->userId);
|
|
|
|
|
|
|
|
|
|
return new ProviderExportResult('customer', $user ? [
|
|
|
|
|
'id' => $user->id,
|
|
|
|
|
'name' => $user->name,
|
|
|
|
|
'email' => $user->email,
|
|
|
|
|
'customers' => $user->customers->map(fn (Customer $customer) => [
|
|
|
|
|
'id' => $customer->id,
|
|
|
|
|
'company_name' => $customer->company_name,
|
|
|
|
|
])->all(),
|
|
|
|
|
] : []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function eraseForCustomer(CustomerSubject $subject): ProviderErasureResult
|
|
|
|
|
{
|
|
|
|
|
$customer = Customer::find($subject->customerId);
|
|
|
|
|
|
|
|
|
|
if (! $customer) {
|
|
|
|
|
return new ProviderErasureResult('customer', ErasureOutcome::Skipped, 'Customer record not found.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$customer->update([
|
|
|
|
|
'title' => null,
|
|
|
|
|
'first_name' => 'Erased',
|
|
|
|
|
'last_name' => "Customer #{$customer->id}",
|
|
|
|
|
'company_name' => null,
|
|
|
|
|
'tax_identifier' => null,
|
|
|
|
|
'account_ref' => null,
|
|
|
|
|
'meta' => null,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return new ProviderErasureResult('customer', ErasureOutcome::Erased);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function eraseForUser(UserSubject $subject): ProviderErasureResult
|
|
|
|
|
{
|
|
|
|
|
$model = config('auth.providers.users.model');
|
|
|
|
|
$user = $model::find($subject->userId);
|
|
|
|
|
|
|
|
|
|
if (! $user) {
|
|
|
|
|
return new ProviderErasureResult('customer', ErasureOutcome::Skipped, 'User record not found.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$user->customers()->detach();
|
|
|
|
|
|
|
|
|
|
$user->update([
|
|
|
|
|
'name' => null,
|
|
|
|
|
'email' => "erased-user-{$user->id}@example.invalid",
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return new ProviderErasureResult('customer', ErasureOutcome::Erased);
|
|
|
|
|
}
|
|
|
|
|
}
|