feat(appointment): update patient identification to use national code from profile and enhance appointment creation logic

This commit is contained in:
hamed
2026-07-15 18:46:56 +03:30
parent 0dc1ab949a
commit de6fe1bd56
8 changed files with 94 additions and 32 deletions
+28 -10
View File
@@ -6,53 +6,71 @@ use App\Auth\Entity\User;
use App\Auth\Repository\UserRepository;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Exception\AppException;
use App\UserProfile\Entity\UserProfile;
use App\UserProfile\Repository\UserProfileRepository;
/**
* Resolves (or creates) the patient User for an admin-side booking.
*
* Identity key is the national code, which is unique per person. Mobile is only
* a contact detail — one national code may be booked under several mobiles — so
* Identity key is the national code, which is stored on the patient's
* UserProfile (unique per person — profiles.national_code). Mobile is only a
* contact detail; one national code may be booked under several mobiles, so
* lookup prefers the national code and never overwrites an existing mobile.
* Keeping resolution here (not duplicated in each controller) keeps the case-file
* (PatientRecord, keyed on user_id) unique per national code.
* Keeping resolution here (not duplicated in each controller) keeps the
* case-file (PatientRecord, keyed on user_id) unique per national code.
*/
class PatientResolver
{
public function __construct(private readonly UserRepository $userRepo) {}
public function __construct(
private readonly UserRepository $userRepo,
private readonly UserProfileRepository $profileRepo,
) {}
/**
* @param string $nationalCode already normalized to English digits and validated
*/
public function resolveForBooking(string $nationalCode, string $mobile, string $name): User
{
$user = $this->userRepo->findByNationalCode($nationalCode);
if ($user !== null) {
// 1) National code lives on the profile and is unique — the real identity.
$profile = $this->profileRepo->findOneByNationalCode($nationalCode);
if ($profile !== null) {
$user = $profile->getUser();
$this->fillNameIfEmpty($user, $name);
return $user;
}
// 2) Fall back to mobile; bind the national code to that patient's profile.
$user = $this->userRepo->findByMobile($mobile);
if ($user !== null) {
$existing = $user->getNationalCode();
$profile = $this->profileRepo->findByUser($user);
$existing = $profile?->getNationalCode();
if ($existing !== null && $existing !== $nationalCode) {
throw new AppException(ErrorCodes::ERR_PROFILE_MOBILE_TAKEN, 'این شماره موبایل با کد ملی دیگری ثبت شده است', 422, 'patient_mobile');
}
if ($existing === null) {
$user->setNationalCode($nationalCode);
$this->bindNationalCode($profile ?? new UserProfile($user), $nationalCode);
}
$this->fillNameIfEmpty($user, $name);
return $user;
}
// 3) New patient: create the user and its profile carrying the national code.
$user = new User($mobile);
$user->setRealName($name);
$user->setNationalCode($nationalCode);
$user->setRoles(['ROLE_USER']);
$this->userRepo->save($user, false);
$this->bindNationalCode(new UserProfile($user), $nationalCode);
return $user;
}
private function bindNationalCode(UserProfile $profile, string $nationalCode): void
{
$profile->setNationalCode($nationalCode);
$this->profileRepo->save($profile, false);
}
private function fillNameIfEmpty(User $user, string $name): void
{
if (($user->getRealName() ?? '') === '' && $name !== '') {