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:
@@ -151,6 +151,15 @@ function MyPatientsPageInner() {
|
|||||||
const [newPatientName, setNewPatientName] = useState("");
|
const [newPatientName, setNewPatientName] = useState("");
|
||||||
const mobileInputRef = useRef<HTMLInputElement>(null);
|
const mobileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const EMPTY_EDIT = {
|
||||||
|
name: "", family: "", national_code: "", gender: "", blood_type: "",
|
||||||
|
marital_status: "", job: "", home_phone: "", work_phone: "", address: "",
|
||||||
|
basic_insurance_id: "", supplementary_insurance_id: "",
|
||||||
|
};
|
||||||
|
const [editOpen, setEditOpen] = useState(false);
|
||||||
|
const [editForm, setEditForm] = useState<Record<string, string>>(EMPTY_EDIT);
|
||||||
|
const setEditField = (k: string, v: string) => setEditForm((f) => ({ ...f, [k]: v }));
|
||||||
|
|
||||||
const servicesTotal = selectedServices.reduce(
|
const servicesTotal = selectedServices.reduce(
|
||||||
(sum, s) => sum + s.price_rials,
|
(sum, s) => sum + s.price_rials,
|
||||||
0,
|
0,
|
||||||
@@ -262,6 +271,60 @@ function MyPatientsPageInner() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openEditInfo = () => {
|
||||||
|
const p = patientProfile;
|
||||||
|
setEditForm({
|
||||||
|
name: p?.name ?? "",
|
||||||
|
family: p?.family ?? "",
|
||||||
|
national_code: p?.national_code ?? "",
|
||||||
|
gender: p?.gender ?? "",
|
||||||
|
blood_type: p?.blood_type ?? "",
|
||||||
|
marital_status: p?.marital_status ?? "",
|
||||||
|
job: p?.job ?? "",
|
||||||
|
home_phone: p?.home_phone ?? "",
|
||||||
|
work_phone: p?.work_phone ?? "",
|
||||||
|
address: p?.address ?? "",
|
||||||
|
basic_insurance_id: p?.basic_insurance_id != null ? String(p.basic_insurance_id) : "",
|
||||||
|
supplementary_insurance_id: p?.supplementary_insurance_id != null ? String(p.supplementary_insurance_id) : "",
|
||||||
|
});
|
||||||
|
setEditOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updatePatientMut = useMutation({
|
||||||
|
mutationFn: (body: object) =>
|
||||||
|
api.patch(`/api/v1/patient/${selectedRecord!.uuid}`, body),
|
||||||
|
onSuccess: () => {
|
||||||
|
qc.invalidateQueries({ queryKey: ["patient-detail", selectedRecord?.uuid] });
|
||||||
|
qc.invalidateQueries({ queryKey: ["patients"] });
|
||||||
|
setEditOpen(false);
|
||||||
|
toast.success("اطلاعات بیمار بهروزرسانی شد");
|
||||||
|
},
|
||||||
|
onError: (e: any) => {
|
||||||
|
toast.error(e?.message || "خطا در بهروزرسانی اطلاعات بیمار");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const submitEditInfo = () => {
|
||||||
|
if (!editForm.name.trim()) {
|
||||||
|
toast.error("نام بیمار الزامی است");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updatePatientMut.mutate({
|
||||||
|
name: editForm.name.trim(),
|
||||||
|
family: editForm.family.trim() || null,
|
||||||
|
national_code: editForm.national_code.trim(),
|
||||||
|
gender: editForm.gender || null,
|
||||||
|
blood_type: editForm.blood_type.trim() || null,
|
||||||
|
marital_status: editForm.marital_status || null,
|
||||||
|
job: editForm.job.trim() || null,
|
||||||
|
home_phone: editForm.home_phone.trim() || null,
|
||||||
|
work_phone: editForm.work_phone.trim() || null,
|
||||||
|
address: editForm.address.trim() || null,
|
||||||
|
basic_insurance_id: editForm.basic_insurance_id ? Number(editForm.basic_insurance_id) : null,
|
||||||
|
supplementary_insurance_id: editForm.supplementary_insurance_id ? Number(editForm.supplementary_insurance_id) : null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const createSessionMut = useMutation({
|
const createSessionMut = useMutation({
|
||||||
mutationFn: (body: object) =>
|
mutationFn: (body: object) =>
|
||||||
api.post(`/api/v1/patient/${selectedRecord!.uuid}/session`, body),
|
api.post(`/api/v1/patient/${selectedRecord!.uuid}/session`, body),
|
||||||
@@ -924,7 +987,12 @@ function MyPatientsPageInner() {
|
|||||||
|
|
||||||
{detailTab === "info" && patientProfile && (
|
{detailTab === "info" && patientProfile && (
|
||||||
<div className="card" style={{ padding: 16, marginBottom: 16 }}>
|
<div className="card" style={{ padding: 16, marginBottom: 16 }}>
|
||||||
<div style={{ fontWeight: 600, fontSize: 14, marginBottom: 12 }}>اطلاعات بیمار</div>
|
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 12 }}>
|
||||||
|
<div style={{ fontWeight: 600, fontSize: 14 }}>اطلاعات بیمار</div>
|
||||||
|
<button className="cp-btn-secondary" style={{ height: 34, padding: "0 12px", fontSize: 13 }} onClick={openEditInfo}>
|
||||||
|
<PencilIcon style={{ width: 15, height: 15 }} /> ویرایش
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: 12 }}>
|
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: 12 }}>
|
||||||
{([
|
{([
|
||||||
["نام کامل", patientProfile.full_name],
|
["نام کامل", patientProfile.full_name],
|
||||||
@@ -951,6 +1019,89 @@ function MyPatientsPageInner() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
open={editOpen}
|
||||||
|
title="ویرایش اطلاعات بیمار"
|
||||||
|
size="lg"
|
||||||
|
onClose={() => setEditOpen(false)}
|
||||||
|
footer={
|
||||||
|
<>
|
||||||
|
<button className="cp-btn-ghost" onClick={() => setEditOpen(false)}>انصراف</button>
|
||||||
|
<button className="cp-btn-primary" onClick={submitEditInfo} disabled={updatePatientMut.isPending}>
|
||||||
|
{updatePatientMut.isPending ? "در حال ذخیره…" : "ذخیره"}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))", gap: 12 }}>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">نام</label>
|
||||||
|
<input className="cp-input" value={editForm.name} onChange={(e) => setEditField("name", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">نام خانوادگی</label>
|
||||||
|
<input className="cp-input" value={editForm.family} onChange={(e) => setEditField("family", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">کد ملی</label>
|
||||||
|
<input className="cp-input" dir="ltr" inputMode="numeric" maxLength={10} value={editForm.national_code} onChange={(e) => setEditField("national_code", e.target.value.replace(/\D/g, ""))} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">جنسیت</label>
|
||||||
|
<select className="cp-select" value={editForm.gender} onChange={(e) => setEditField("gender", e.target.value)}>
|
||||||
|
<option value="">—</option>
|
||||||
|
<option value="male">مرد</option>
|
||||||
|
<option value="female">زن</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">گروه خونی</label>
|
||||||
|
<input className="cp-input" value={editForm.blood_type} onChange={(e) => setEditField("blood_type", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">وضعیت تأهل</label>
|
||||||
|
<select className="cp-select" value={editForm.marital_status} onChange={(e) => setEditField("marital_status", e.target.value)}>
|
||||||
|
<option value="">—</option>
|
||||||
|
<option value="single">مجرد</option>
|
||||||
|
<option value="married">متأهل</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">شغل</label>
|
||||||
|
<input className="cp-input" value={editForm.job} onChange={(e) => setEditField("job", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">تلفن منزل</label>
|
||||||
|
<input className="cp-input" dir="ltr" value={editForm.home_phone} onChange={(e) => setEditField("home_phone", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">تلفن محل کار</label>
|
||||||
|
<input className="cp-input" dir="ltr" value={editForm.work_phone} onChange={(e) => setEditField("work_phone", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">بیمه پایه</label>
|
||||||
|
<select className="cp-select" value={editForm.basic_insurance_id} onChange={(e) => setEditField("basic_insurance_id", e.target.value)}>
|
||||||
|
<option value="">—</option>
|
||||||
|
{baseInsuranceOptions.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="cp-label">بیمه تکمیلی</label>
|
||||||
|
<select className="cp-select" value={editForm.supplementary_insurance_id} onChange={(e) => setEditField("supplementary_insurance_id", e.target.value)}>
|
||||||
|
<option value="">—</option>
|
||||||
|
{suppInsuranceOptions.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: 12 }}>
|
||||||
|
<label className="cp-label">آدرس</label>
|
||||||
|
<textarea className="cp-textarea" rows={2} value={editForm.address} onChange={(e) => setEditField("address", e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: 12, fontSize: 12, color: "var(--text-3)" }}>
|
||||||
|
شماره موبایل ({patientProfile?.mobile}) شناسهی حساب بیمار است و از اینجا قابل تغییر نیست.
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
{detailTab === "sessions" && (
|
{detailTab === "sessions" && (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -459,6 +459,8 @@ export interface SmsSettings {
|
|||||||
|
|
||||||
export interface PatientProfile {
|
export interface PatientProfile {
|
||||||
full_name?: string | null;
|
full_name?: string | null;
|
||||||
|
name?: string | null;
|
||||||
|
family?: string | null;
|
||||||
national_code?: string | null;
|
national_code?: string | null;
|
||||||
gender?: string | null;
|
gender?: string | null;
|
||||||
date_of_birth?: number | null;
|
date_of_birth?: number | null;
|
||||||
@@ -469,7 +471,9 @@ export interface PatientProfile {
|
|||||||
home_phone?: string | null;
|
home_phone?: string | null;
|
||||||
work_phone?: string | null;
|
work_phone?: string | null;
|
||||||
mobile?: string | null;
|
mobile?: string | null;
|
||||||
|
basic_insurance_id?: number | null;
|
||||||
basic_insurance_name?: string | null;
|
basic_insurance_name?: string | null;
|
||||||
|
supplementary_insurance_id?: number | null;
|
||||||
supplementary_insurance_name?: string | null;
|
supplementary_insurance_name?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ Returns a single patient record, enriched with the patient's full profile (`prof
|
|||||||
"created_at": 1718375000,
|
"created_at": 1718375000,
|
||||||
"profile": {
|
"profile": {
|
||||||
"full_name": "محمد محمدی",
|
"full_name": "محمد محمدی",
|
||||||
|
"name": "محمد",
|
||||||
|
"family": "محمدی",
|
||||||
"national_code": "0012345678",
|
"national_code": "0012345678",
|
||||||
"gender": "male",
|
"gender": "male",
|
||||||
"date_of_birth": 700000000,
|
"date_of_birth": 700000000,
|
||||||
@@ -169,6 +171,63 @@ Returns a single patient record, enriched with the patient's full profile (`prof
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Update Patient Basic Info
|
||||||
|
|
||||||
|
```
|
||||||
|
PATCH /api/v1/patient/{uuid}
|
||||||
|
```
|
||||||
|
|
||||||
|
اطلاعات پایهی بیمار را بهروزرسانی میکند. برای هر سه نقشِ صاحبِ پرونده در دسترس است: **پزشک، کلینیک، و منشیِ فعالِ همان مطب/کلینیک** (دسترسی از طریق همان `resolveEntity` + `assertPatientGate` مثل بقیهی endpointهای بیمار کنترل میشود؛ منشی باید `db_uuid` فعال داشته باشد).
|
||||||
|
|
||||||
|
بهروزرسانی **partial** است — فقط کلیدهای ارسالشده اعمال میشوند. مقدار `""`/`null` برای فیلدهای پروفایل یعنی «پاککردن». `name` روی `User.realName` و بقیهی فیلدها روی `UserProfile` مینشینند (در صورت نبود پروفایل، ساخته میشود).
|
||||||
|
|
||||||
|
> **شماره موبایل قابل ویرایش نیست** — شناسهی حساب کاربر است و در این endpoint نادیده گرفته میشود.
|
||||||
|
|
||||||
|
**Request body:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "محمد",
|
||||||
|
"family": "محمدی",
|
||||||
|
"national_code": "0012345678",
|
||||||
|
"gender": "male",
|
||||||
|
"blood_type": "O+",
|
||||||
|
"marital_status": "single",
|
||||||
|
"job": "مهندس",
|
||||||
|
"home_phone": "03511111111",
|
||||||
|
"work_phone": "03512222222",
|
||||||
|
"address": "...",
|
||||||
|
"basic_insurance_id": 3,
|
||||||
|
"supplementary_insurance_id": 9
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Type | Notes |
|
||||||
|
|-------|------|-------|
|
||||||
|
| `name` | string | اگر ارسال شود و خالی نباشد → `User.realName`. رشتهی خالی نادیده گرفته میشود. |
|
||||||
|
| `family` | string\|null | `UserProfile.family` |
|
||||||
|
| `national_code` | string\|null | اگر خالی نباشد باید ۱۰ رقم و در سطح بیمار یکتا باشد؛ روی `User.nationalCode` و `UserProfile.nationalCode` ست میشود |
|
||||||
|
| `gender` | `male`\|`female`\|null | |
|
||||||
|
| `blood_type` | string\|null | |
|
||||||
|
| `marital_status` | string\|null | |
|
||||||
|
| `job` | string\|null | |
|
||||||
|
| `home_phone`, `work_phone` | string\|null | |
|
||||||
|
| `address` | string\|null | |
|
||||||
|
| `basic_insurance_id`, `supplementary_insurance_id` | int\|null | id بیمه؛ `null` = حذف |
|
||||||
|
|
||||||
|
**Response 200:** مثل `GET /api/v1/patient/{uuid}` (رکورد + `profile` تازه).
|
||||||
|
|
||||||
|
**Errors:**
|
||||||
|
|
||||||
|
| Code | HTTP | Description |
|
||||||
|
|------|------|-------------|
|
||||||
|
| `ERR_PATIENT_NOT_FOUND` | 404 | Record not found or not owned by caller |
|
||||||
|
| `ERR_VALIDATION_001` | 422 | کد ملی باید ۱۰ رقم باشد (`field: national_code`) |
|
||||||
|
| `ERR_PROFILE_NATIONAL_CODE_TAKEN` | 409 | کد ملی متعلق به بیمار دیگری است (`field: national_code`) |
|
||||||
|
| `ERR_SUBSCRIPTION_REQUIRED` | 403 | No `patient_records` feature |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### List Patient Sessions
|
### List Patient Sessions
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use App\Secretary\Repository\DoctorSecretaryRepository;
|
|||||||
use App\Patient\Repository\PatientRecordRepository;
|
use App\Patient\Repository\PatientRecordRepository;
|
||||||
use App\Patient\Repository\PatientSessionRepository;
|
use App\Patient\Repository\PatientSessionRepository;
|
||||||
use App\Patient\Service\PatientService;
|
use App\Patient\Service\PatientService;
|
||||||
|
use App\UserProfile\Entity\UserProfile;
|
||||||
use App\Shared\Constant\ErrorCodes;
|
use App\Shared\Constant\ErrorCodes;
|
||||||
use App\Shared\Controller\BaseController;
|
use App\Shared\Controller\BaseController;
|
||||||
use App\Shared\Exception\AppException;
|
use App\Shared\Exception\AppException;
|
||||||
@@ -57,6 +58,8 @@ class PatientController extends BaseController
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'full_name' => trim(($patient->getRealName() ?? '') . ' ' . ($p?->getFamily() ?? '')) ?: $patient->getRealName(),
|
'full_name' => trim(($patient->getRealName() ?? '') . ' ' . ($p?->getFamily() ?? '')) ?: $patient->getRealName(),
|
||||||
|
'name' => $patient->getRealName(),
|
||||||
|
'family' => $p?->getFamily(),
|
||||||
'national_code' => $p?->getNationalCode() ?? $patient->getNationalCode(),
|
'national_code' => $p?->getNationalCode() ?? $patient->getNationalCode(),
|
||||||
'gender' => $p?->getGender(),
|
'gender' => $p?->getGender(),
|
||||||
'date_of_birth' => $p?->getDateOfBirth(),
|
'date_of_birth' => $p?->getDateOfBirth(),
|
||||||
@@ -203,6 +206,92 @@ class PatientController extends BaseController
|
|||||||
return $this->success($data);
|
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'])]
|
#[Route('/api/v1/patient/{uuid}/sessions', methods: ['GET'])]
|
||||||
public function sessions(string $uuid, Request $request, #[CurrentUser] User $user): JsonResponse
|
public function sessions(string $uuid, Request $request, #[CurrentUser] User $user): JsonResponse
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user