feat(invoice): implement recorder identity resolution for payments and update related tests

This commit is contained in:
hamed
2026-08-04 11:19:07 +03:30
parent 2c7b86d917
commit 810e9351a9
7 changed files with 321 additions and 13 deletions
@@ -0,0 +1,79 @@
<?php
namespace App\Shared\Service;
use App\Auth\Entity\User;
use App\Doctor\Repository\DoctorRepository;
use App\UserProfile\Repository\UserProfileRepository;
/**
* «چه کسی این را ثبت کرد» — نامِ نمایشی و هویتِ کاربرِ عامل، یک جا.
*
* ستون‌های `created_by_name` عکسِ لحظهٔ ثبت‌اند و ممکن است شمارهٔ موبایل باشند (وقتی
* کاربر هنوز پروفایل نداشته). برای نمایش، نام از خودِ کاربر دوباره حل می‌شود تا
* فاکتورِ دیروز هم نامِ امروز را نشان دهد؛ عکسِ ذخیره‌شده فقط وقتی می‌ماند که کاربر
* حذف شده باشد.
*/
class ActorIdentityResolver
{
public function __construct(
private readonly UserProfileRepository $profileRepo,
private readonly DoctorRepository $doctorRepo,
) {}
/** نامِ نمایشی: پروفایل ← نام واقعیِ حساب ← شمارهٔ موبایل. */
public function name(?User $actor): ?string
{
if ($actor === null) {
return null;
}
$profile = $this->profileRepo->findByUser($actor);
$name = trim(($profile?->getLabel() ?? '') . ' ' . ($profile?->getFamily() ?? ''));
if ($name !== '') {
return $name;
}
$realName = trim((string) $actor->getRealName());
return $realName !== '' ? $realName : $actor->getMobileNumber();
}
/**
* هویتِ کاملِ عامل برای نمایش و لینک‌دادن به پروفایلش.
*
* `doctor_uuid` فقط برای پزشک پر می‌شود — تنها نقشی که در پنل صفحهٔ پروفایلِ
* مستقل دارد. مسیرِ لینک کارِ کلاینت است، نه سرور: سرور مسیرهای پنل را نمی‌داند.
*
* @return array{user_uuid:string,name:?string,role:string,doctor_uuid:?string}|null
*/
public function identity(?User $actor): ?array
{
if ($actor === null) {
return null;
}
$role = $this->primaryRole($actor);
return [
'user_uuid' => $actor->getUuid(),
'name' => $this->name($actor),
'role' => $role,
'doctor_uuid' => $role === 'doctor' ? $this->doctorRepo->findByUser($actor)?->getUuid() : null,
];
}
/** همان اولویتِ نقشِ `oauth/userinfo` — پرتوان‌ترین نقش برنده است. */
private function primaryRole(User $actor): string
{
$roles = $actor->getRoles();
if (in_array('ROLE_ADMIN', $roles, true)) return 'admin';
if (in_array('ROLE_CLINIC', $roles, true)) return 'clinic';
if (in_array('ROLE_DOCTOR', $roles, true)) return 'doctor';
if (in_array('ROLE_SECRETARY', $roles, true)) return 'secretary';
if (in_array('ROLE_STAFF', $roles, true)) return 'staff';
if (in_array('ROLE_REPRESENTATION', $roles, true)) return 'representation';
return 'user';
}
}