feat(patient): edit patient basic info (doctor/clinic/secretary)
Add PATCH /api/v1/patient/{uuid} to update User.realName + UserProfile
demographic/insurance fields (mobile stays immutable, national_code
uniqueness enforced). Expose name/family separately in profile payload.
Add edit modal in my-patients. Update patient.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ use App\Secretary\Repository\DoctorSecretaryRepository;
|
||||
use App\Patient\Repository\PatientRecordRepository;
|
||||
use App\Patient\Repository\PatientSessionRepository;
|
||||
use App\Patient\Service\PatientService;
|
||||
use App\UserProfile\Entity\UserProfile;
|
||||
use App\Shared\Constant\ErrorCodes;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use App\Shared\Exception\AppException;
|
||||
@@ -57,6 +58,8 @@ class PatientController extends BaseController
|
||||
|
||||
return [
|
||||
'full_name' => trim(($patient->getRealName() ?? '') . ' ' . ($p?->getFamily() ?? '')) ?: $patient->getRealName(),
|
||||
'name' => $patient->getRealName(),
|
||||
'family' => $p?->getFamily(),
|
||||
'national_code' => $p?->getNationalCode() ?? $patient->getNationalCode(),
|
||||
'gender' => $p?->getGender(),
|
||||
'date_of_birth' => $p?->getDateOfBirth(),
|
||||
@@ -203,6 +206,92 @@ class PatientController extends BaseController
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/patient/{uuid}', methods: ['PATCH'])]
|
||||
public function update(string $uuid, Request $request, #[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
[$entityType, $entityId] = $this->resolveEntity($user);
|
||||
$this->assertPatientGate($entityType, $entityId);
|
||||
|
||||
$record = $this->recordRepo->findByUuid($uuid);
|
||||
if ($record === null || !$this->ownsRecord($record, $entityType, $entityId)) {
|
||||
return $this->error(ErrorCodes::ERR_PATIENT_NOT_FOUND, ErrorCodes::message(ErrorCodes::ERR_PATIENT_NOT_FOUND), 404);
|
||||
}
|
||||
|
||||
$patient = $record->getUser();
|
||||
$data = json_decode($request->getContent(), true) ?? [];
|
||||
|
||||
if (array_key_exists('name', $data)) {
|
||||
$name = trim((string) $data['name']);
|
||||
if ($name !== '') {
|
||||
$patient->setRealName($name);
|
||||
}
|
||||
}
|
||||
|
||||
// کد ملی باید ۱۰ رقم و در سطح بیمار یکتا باشد
|
||||
if (array_key_exists('national_code', $data)) {
|
||||
$nationalCode = trim((string) ($data['national_code'] ?? ''));
|
||||
if ($nationalCode !== '') {
|
||||
if (!preg_match('/^\d{10}$/', $nationalCode)) {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'کد ملی باید ۱۰ رقم باشد', 422, 'national_code');
|
||||
}
|
||||
$owner = $this->profileRepo->findOneByNationalCode($nationalCode);
|
||||
if ($owner !== null && $owner->getUser()->getId() !== $patient->getId()) {
|
||||
$masked = \App\Shared\Service\InputValidator::maskMobile($owner->getUser()->getMobileNumber());
|
||||
return $this->error(
|
||||
ErrorCodes::ERR_PROFILE_NATIONAL_CODE_TAKEN,
|
||||
"این کد ملی قبلاً با شماره {$masked} ثبت شده است",
|
||||
409,
|
||||
'national_code'
|
||||
);
|
||||
}
|
||||
$patient->setNationalCode($nationalCode);
|
||||
}
|
||||
}
|
||||
$this->userRepo->save($patient);
|
||||
|
||||
$profile = $this->profileRepo->findByUser($patient) ?? new UserProfile($patient);
|
||||
|
||||
$stringFields = [
|
||||
'family' => 'setFamily',
|
||||
'gender' => 'setGender',
|
||||
'blood_type' => 'setBloodType',
|
||||
'marital_status' => 'setMaritalStatus',
|
||||
'job' => 'setJob',
|
||||
'address' => 'setAddress',
|
||||
'home_phone' => 'setHomePhone',
|
||||
'work_phone' => 'setWorkPhone',
|
||||
];
|
||||
foreach ($stringFields as $key => $setter) {
|
||||
if (array_key_exists($key, $data)) {
|
||||
$v = is_string($data[$key]) ? trim($data[$key]) : $data[$key];
|
||||
$profile->$setter($v === '' ? null : $v);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('national_code', $data)) {
|
||||
$nc = trim((string) ($data['national_code'] ?? ''));
|
||||
$profile->setNationalCode($nc === '' ? null : $nc);
|
||||
}
|
||||
if (array_key_exists('date_of_birth', $data)) {
|
||||
$dob = $data['date_of_birth'];
|
||||
$profile->setDateOfBirth(($dob === null || $dob === '') ? null : (int) $dob);
|
||||
}
|
||||
if (array_key_exists('basic_insurance_id', $data)) {
|
||||
$bi = $data['basic_insurance_id'];
|
||||
$profile->setBasicInsuranceId(($bi === null || $bi === '') ? null : (int) $bi);
|
||||
}
|
||||
if (array_key_exists('supplementary_insurance_id', $data)) {
|
||||
$si = $data['supplementary_insurance_id'];
|
||||
$profile->setSupplementaryInsuranceId(($si === null || $si === '') ? null : (int) $si);
|
||||
}
|
||||
$this->profileRepo->save($profile);
|
||||
|
||||
$out = $record->toArray();
|
||||
$out['profile'] = $this->buildPatientProfile($patient);
|
||||
|
||||
return $this->success($out);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/patient/{uuid}/sessions', methods: ['GET'])]
|
||||
public function sessions(string $uuid, Request $request, #[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user