Add JSON files for security audit and test data

- Created a JSON file for the security audit report dated 2026-07-19, detailing various security findings and their relationships.
- Added a JSON file for seed test data, including user creation logic and dependencies in the `seed_testdata.php` file.
- Introduced a JSON file for the AdminCspSubscriberTest, outlining test cases and their structure in the `AdminCspSubscriberTest.php`.
This commit is contained in:
hamed
2026-07-23 15:12:37 +03:30
parent 9a776be13c
commit 0edaf6518f
17 changed files with 2085 additions and 1687 deletions
@@ -95,6 +95,50 @@ describe('NewAppointmentModal — جستجوی موبایل‌محور', () => {
});
});
describe('NewAppointmentModal — جستجو با کد ملی', () => {
it('searches by national_code and books the found patient with its mobile', async () => {
get.mockResolvedValue({ success: true, data: { found: true, name: 'رضا کریمی', mobile: '09121112233', national_code: '0012345678' } });
renderWithProviders(<NewAppointmentModal slot={slot} onClose={() => {}} onSuccess={() => {}} />);
// تغییر معیار جستجو به کد ملی
fireEvent.click(screen.getByRole('button', { name: 'کد ملی' }));
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
await waitFor(() => expect(get).toHaveBeenCalledWith('/api/v1/my/appointment/patient-lookup?national_code=0012345678'));
await screen.findByText('بیمار یافت شد');
fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));
await waitFor(() => expect(post).toHaveBeenCalledWith('/api/v1/my/appointment', expect.objectContaining({
patient_mobile: '09121112233',
patient_name: 'رضا کریمی',
patient_national_code: '0012345678',
})));
});
it('unknown national code reveals mobile + name fields and books the new patient', async () => {
get.mockResolvedValue({ success: true, data: { found: false } });
renderWithProviders(<NewAppointmentModal slot={slot} onClose={() => {}} onSuccess={() => {}} />);
fireEvent.click(screen.getByRole('button', { name: 'کد ملی' }));
fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '1234567891' } });
fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
// موبایل خواسته می‌شود؛ کد ملی فقط همان ورودیِ جستجو است (بدون فیلد تکراری)
const mob = await screen.findByPlaceholderText('مثال: 09123456789');
expect(screen.getAllByPlaceholderText('کد ملی ۱۰ رقمی')).toHaveLength(1);
fireEvent.change(screen.getByPlaceholderText('مثال: علی محمدی'), { target: { value: 'مریم خلیلی' } });
fireEvent.change(mob, { target: { value: '09990001122' } });
fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));
await waitFor(() => expect(post).toHaveBeenCalledWith('/api/v1/my/appointment', expect.objectContaining({
patient_mobile: '09990001122',
patient_name: 'مریم خلیلی',
patient_national_code: '1234567891',
})));
});
});
describe('NewAppointmentModal — هزینه ویزیت', () => {
/** تعرفه را برای همان پزشکِ اسلات برمی‌گرداند؛ بقیهٔ GETها بیمارِ ناشناس. */
function mockPricing(rials: number, requireVisit = false) {
+162 -55
View File
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate, useSearchParams } from 'react-router-dom';
import {
PlusIcon, ChevronRightIcon, ChevronLeftIcon, CalendarDaysIcon,
PlusIcon, ChevronRightIcon, ChevronLeftIcon, ChevronDownIcon, CalendarDaysIcon,
AdjustmentsHorizontalIcon, ClockIcon, MagnifyingGlassIcon, CheckCircleIcon,
} from '@heroicons/react/24/outline';
import { toast } from 'sonner';
@@ -118,6 +118,8 @@ export function NewAppointmentModal({
const [lookup, setLookup] = useState<PatientLookup | null>(null);
const [patientName, setPatientName] = useState('');
const [nationalCode, setNationalCode] = useState('');
// معیار جستجوی بیمار: موبایل یا کد ملی.
const [searchBy, setSearchBy] = useState<'mobile' | 'national'>('mobile');
const [pick, setPick] = useState<{ serviceUuids: string[]; slot: { start: number; end: number } | null }>({ serviceUuids: [], slot: null });
const role = useAuthStore(s => s.primaryRole);
@@ -149,8 +151,14 @@ export function NewAppointmentModal({
useEffect(() => {
if (!visitPriceTouched && freeVisit > 0) setVisitPriceToman(rialToToman(freeVisit));
}, [freeVisit, visitPriceTouched]);
// هزینه ویزیت اختیاری داخل کلپسِ بسته می‌نشیند؛ وقتی الزامی است کلپس همیشه باز است.
const [visitPriceOpen, setVisitPriceOpen] = useState(false);
const visitPriceExpanded = requireVisit || visitPriceOpen;
const mobileValid = /^09\d{9}$/.test(mobile);
const nationalCodeValid = /^\d{10}$/.test(nationalCode);
// اعتبار کلید جستجو بسته به معیار انتخاب‌شده.
const searchValid = searchBy === 'mobile' ? mobileValid : nationalCodeValid;
const serviceTimingValid = !serviceMode || (pick.serviceUuids.length > 0 && !!pick.slot);
// یک بیمارِ یافت‌شده که کد ملی دارد، بدون فرم اضافی قابل استفاده است.
const foundWithNationalCode = !!lookup?.found && !!lookup.national_code;
@@ -163,12 +171,23 @@ export function NewAppointmentModal({
const isValid = mobileValid && (foundWithNationalCode || (needsDetails && detailsValid)) && serviceTimingValid && visitPriceValid;
const search = useMutation({
mutationFn: () => api.get(`/api/v1/my/appointment/patient-lookup?mobile=${encodeURIComponent(mobile)}`),
mutationFn: () => {
const q = searchBy === 'mobile'
? `mobile=${encodeURIComponent(mobile)}`
: `national_code=${encodeURIComponent(nationalCode)}`;
return api.get(`/api/v1/my/appointment/patient-lookup?${q}`);
},
onSuccess: (res: any) => {
const data: PatientLookup = res?.data ?? { found: false };
setLookup(data);
setPatientName(data.found ? (data.name ?? '') : '');
setNationalCode(data.found ? (data.national_code ?? '') : '');
// موبایل و کد ملیِ بیمارِ یافت‌شده را پر می‌کنیم تا ثبت مستقل از معیار جستجو کار کند.
if (data.found) {
if (data.mobile) setMobile(data.mobile);
setNationalCode(data.national_code ?? '');
} else if (searchBy === 'mobile') {
setNationalCode('');
}
},
onError: (e: any) => toast.error(e?.response?.data?.errors?.[0]?.message ?? e?.message ?? 'خطا در جستجو'),
});
@@ -196,11 +215,24 @@ export function NewAppointmentModal({
},
});
// تغییر موبایل نتیجه‌ی جستجوی قبلی را باطل می‌کند تا کاربر دوباره جستجو کند.
// تغییر کلید جستجو نتیجه‌ی جستجوی قبلی را باطل می‌کند تا کاربر دوباره جستجو کند.
function invalidateLookup() {
if (lookup !== null) { setLookup(null); setPatientName(''); }
}
function onMobileChange(v: string) {
// ارقام فارسی/عربی → انگلیسی، فقط رقم، حداکثر ۱۱ رقم (کیبورد فارسی هم پذیرفته می‌شود).
setMobile(sanitizeMobileInput(v));
if (lookup !== null) { setLookup(null); setPatientName(''); setNationalCode(''); }
if (lookup !== null) { setLookup(null); setPatientName(''); if (searchBy === 'mobile') setNationalCode(''); }
}
function onNationalSearchChange(v: string) {
setNationalCode(digitsOnly(v, 10));
invalidateLookup();
}
// جابه‌جایی معیار جستجو همه‌چیز را از نو شروع می‌کند.
function onSwitchSearchBy(mode: 'mobile' | 'national') {
setSearchBy(mode);
setLookup(null); setPatientName('');
setMobile(''); setNationalCode('');
}
const priceHint = pricingLoading
@@ -257,25 +289,54 @@ export function NewAppointmentModal({
)}
<div className="field-block" style={{ marginBottom: 14 }}>
<label>شماره موبایل بیمار <span className="req">*</span></label>
<label>جستجوی بیمار <span className="req">*</span></label>
{/* انتخاب معیار جستجو: موبایل یا کد ملی */}
<div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
{(['mobile', 'national'] as const).map(mode => (
<button
key={mode}
type="button"
className={`btn sm ${searchBy === mode ? 'primary' : 'ghost'}`}
onClick={() => onSwitchSearchBy(mode)}
style={{ flex: 1 }}
>
{mode === 'mobile' ? 'شماره موبایل' : 'کد ملی'}
</button>
))}
</div>
<div style={{ display: 'flex', gap: 8 }}>
<div className="field" style={{ flex: 1 }}>
<input
type="tel"
inputMode="numeric"
maxLength={11}
value={mobile}
onChange={e => onMobileChange(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter' && mobileValid && !search.isPending) search.mutate(); }}
placeholder="مثال: 09123456789"
style={{ direction: 'ltr' }}
autoFocus
/>
{searchBy === 'mobile' ? (
<input
type="tel"
inputMode="numeric"
maxLength={11}
value={mobile}
onChange={e => onMobileChange(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter' && searchValid && !search.isPending) search.mutate(); }}
placeholder="مثال: 09123456789"
style={{ direction: 'ltr' }}
autoFocus
/>
) : (
<input
type="text"
inputMode="numeric"
lang="en"
maxLength={10}
value={nationalCode}
onChange={e => onNationalSearchChange(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter' && searchValid && !search.isPending) search.mutate(); }}
placeholder="کد ملی ۱۰ رقمی"
style={{ direction: 'ltr' }}
autoFocus
/>
)}
</div>
<button
className="btn soft"
onClick={() => search.mutate()}
disabled={!mobileValid || search.isPending}
disabled={!searchValid || search.isPending}
style={{ whiteSpace: 'nowrap' }}
>
<MagnifyingGlassIcon style={{ width: 16, height: 16 }} />
@@ -305,7 +366,7 @@ export function NewAppointmentModal({
fontSize: 12.5, color: 'var(--text-2)', marginBottom: 12,
padding: '9px 12px', borderRadius: 'var(--r-sm)', background: 'var(--warning-bg)',
}}>
{lookup?.found ? 'برای این بیمار کد ملی ثبت نشده — لطفاً تکمیل کنید:' : 'کاربری با این شماره یافت نشد — بیمار جدید:'}
{lookup?.found ? 'برای این بیمار کد ملی ثبت نشده — لطفاً تکمیل کنید:' : یماری با این مشخصات یافت نشد — بیمار جدید:'}
</div>
<div className="field-block" style={{ marginBottom: 14 }}>
<label>نام و نام خانوادگی بیمار <span className="req">*</span></label>
@@ -318,52 +379,98 @@ export function NewAppointmentModal({
/>
</div>
</div>
<div className="field-block" style={{ marginBottom: 14 }}>
<label>کد ملی بیمار <span className="req">*</span></label>
<div className="field">
<input
type="text"
inputMode="numeric"
lang="en"
maxLength={10}
value={nationalCode}
onChange={e => setNationalCode(digitsOnly(e.target.value, 10))}
placeholder="کد ملی ۱۰ رقمی"
style={{ direction: 'ltr' }}
/>
{/* در جستجو با کد ملی، موبایل هنوز نامعلوم است و برای ثبت لازم می‌شود. */}
{searchBy === 'national' && (
<div className="field-block" style={{ marginBottom: 14 }}>
<label>شماره موبایل بیمار <span className="req">*</span></label>
<div className="field">
<input
type="tel"
inputMode="numeric"
maxLength={11}
value={mobile}
onChange={e => setMobile(sanitizeMobileInput(e.target.value))}
placeholder="مثال: 09123456789"
style={{ direction: 'ltr' }}
/>
</div>
</div>
</div>
)}
{/* در جستجو با کد ملی، همان مقدار کلیدِ جستجو استفاده می‌شود و فیلد تکراری لازم نیست. */}
{searchBy === 'mobile' && (
<div className="field-block" style={{ marginBottom: 14 }}>
<label>کد ملی بیمار <span className="req">*</span></label>
<div className="field">
<input
type="text"
inputMode="numeric"
lang="en"
maxLength={10}
value={nationalCode}
onChange={e => setNationalCode(digitsOnly(e.target.value, 10))}
placeholder="کد ملی ۱۰ رقمی"
style={{ direction: 'ltr' }}
/>
</div>
</div>
)}
</>
)}
<div className="field-block">
<label>
هزینه ویزیت (تومان)
{requireVisit ? <span className="req"> *</span> : <span className="opt">(اختیاری)</span>}
</label>
<div
className="field"
style={requireVisit && visitPriceToman <= 0 ? { borderColor: 'var(--danger)' } : undefined}
>
<PriceInput
value={visitPriceToman}
onChange={(v) => { setVisitPriceToman(v); setVisitPriceTouched(true); }}
suffix="تومان"
/>
</div>
{requireVisit && visitPriceToman <= 0
? <span className="field-err">هزینه ویزیت الزامی است</span>
: <span className="field-hint">{priceHint}</span>}
{freeVisit > 0 && visitPriceToman !== rialToToman(freeVisit) && (
{requireVisit ? (
<label>
هزینه ویزیت (تومان)<span className="req"> *</span>
</label>
) : (
// سرِ کلپس — با کلیک باز/بسته می‌شود (فقط وقتی اختیاری است).
<button
type="button"
className="btn ghost sm"
style={{ marginTop: 8, alignSelf: 'flex-start' }}
onClick={() => { setVisitPriceToman(rialToToman(freeVisit)); setVisitPriceTouched(true); }}
onClick={() => setVisitPriceOpen(o => !o)}
aria-expanded={visitPriceExpanded}
style={{
display: 'flex', alignItems: 'center', gap: 6, width: '100%',
background: 'none', border: 'none', cursor: 'pointer', font: 'inherit',
padding: 0, color: 'var(--text)',
}}
>
استفاده از تعرفهٔ پزشک
<span>هزینه ویزیت (تومان) <span className="opt">(اختیاری)</span></span>
<ChevronDownIcon
style={{
width: 15, height: 15, marginInlineStart: 'auto', flexShrink: 0,
transition: 'transform .2s var(--ease)',
transform: visitPriceExpanded ? 'rotate(180deg)' : 'none',
}}
/>
</button>
)}
{visitPriceExpanded && (
<>
<div
className="field"
style={requireVisit && visitPriceToman <= 0 ? { borderColor: 'var(--danger)' } : undefined}
>
<PriceInput
value={visitPriceToman}
onChange={(v) => { setVisitPriceToman(v); setVisitPriceTouched(true); }}
suffix="تومان"
/>
</div>
{requireVisit && visitPriceToman <= 0
? <span className="field-err">هزینه ویزیت الزامی است</span>
: <span className="field-hint">{priceHint}</span>}
{freeVisit > 0 && visitPriceToman !== rialToToman(freeVisit) && (
<button
type="button"
className="btn ghost sm"
style={{ marginTop: 8, alignSelf: 'flex-start' }}
onClick={() => { setVisitPriceToman(rialToToman(freeVisit)); setVisitPriceTouched(true); }}
>
استفاده از تعرفهٔ پزشک
</button>
)}
</>
)}
</div>
</Modal>
);
+6 -3
View File
@@ -707,16 +707,19 @@ Create a new appointment for a patient. Used by doctor/clinic/secretary to book
## GET `/api/v1/my/appointment/patient-lookup`
جستجوی بیمار با شماره موبایل، پیش از ثبت نوبت. فرم ثبت نوبت اول با موبایل جستجو می‌کند؛ اگر بیمار یافت شد و کد ملی دارد، مستقیم استفاده می‌شود، وگرنه کد ملی و نام از کاربر گرفته می‌شود.
جستجوی بیمار با شماره موبایل **یا** کد ملی، پیش از ثبت نوبت. فرم ثبت نوبت با یکی از این دو معیار جستجو می‌کند؛ اگر بیمار یافت شد و کد ملی دارد، مستقیم استفاده می‌شود، وگرنه بقیهٔ مشخصات (نام و موبایل یا کد ملی) از کاربر گرفته می‌شود.
**Auth:** `IS_AUTHENTICATED_FULLY` — Roles: `ROLE_DOCTOR`, `ROLE_CLINIC`, `ROLE_SECRETARY`, `ROLE_ADMIN`
> برخلاف `GET /api/v1/patient/search-user`، این endpoint به فیچر `patient_records` اشتراک وابسته نیست و `ROLE_ADMIN` را هم می‌پذیرد، چون ثبت نوبت باید مستقل از اشتراک کار کند.
### Query Parameters
یکی از `mobile` یا `national_code` الزامی است. اگر هر دو ارسال شوند، `national_code` اولویت دارد.
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `mobile` | string | | شماره موبایل ایران (`^09\d{9}$`)؛ ارقام فارسی به انگلیسی تبدیل می‌شوند |
| `mobile` | string | یکی از دو | شماره موبایل ایران (`^09\d{9}$`)؛ ارقام فارسی به انگلیسی تبدیل می‌شوند |
| `national_code` | string | یکی از دو | کد ملی ۱۰ رقمی (`^\d{10}$`)؛ ارقام فارسی به انگلیسی تبدیل می‌شوند |
### Response `200` — یافت شد
```json
@@ -741,7 +744,7 @@ Create a new appointment for a patient. Used by doctor/clinic/secretary to book
| Code | HTTP | Description |
|------|------|-------------|
| `FORBIDDEN` | 403 | Role not allowed |
| `VALIDATION` | 422 | Invalid `mobile` (`field: mobile`) |
| `VALIDATION` | 422 | Invalid `national_code` (`field: national_code`)، یا هیچ‌کدام از `mobile`/`national_code` معتبر نبود (`field: mobile`) |
---
+1
View File
@@ -1013,6 +1013,7 @@
"1011": "Community 1011",
"1012": "Community 1012",
"1013": "Community 1013",
"1014": "Community 1014",
"1015": "Community 1015",
"1016": "Community 1016",
"1017": "Community 1017",
+164 -167
View File
@@ -1,16 +1,16 @@
# Graph Report - clinicpro (2026-07-22)
# Graph Report - clinicpro (2026-07-23)
## Corpus Check
- 1192 files · ~852,314 words
- 1193 files · ~853,642 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 13946 nodes · 21763 edges · 1018 communities (781 shown, 237 thin omitted)
- 13952 nodes · 21775 edges · 1019 communities (780 shown, 239 thin omitted)
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 465 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `c94ceaa0`
- Built from commit: `9a776be1`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -1011,6 +1011,7 @@
- [[_COMMUNITY_Community 1011|Community 1011]]
- [[_COMMUNITY_Community 1012|Community 1012]]
- [[_COMMUNITY_Community 1013|Community 1013]]
- [[_COMMUNITY_Community 1014|Community 1014]]
- [[_COMMUNITY_Community 1015|Community 1015]]
- [[_COMMUNITY_Community 1016|Community 1016]]
- [[_COMMUNITY_Community 1017|Community 1017]]
@@ -1043,15 +1044,15 @@
## Import Cycles
- None detected.
## Communities (1018 total, 237 thin omitted)
## Communities (1019 total, 239 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.06
Nodes (19): ClinicAppointmentAccessTest, ClinicDoctorPermissionTest, ClinicDoctorPermissionRepository, ClinicDoctorPermission, ClinicRecordAccessTest, ClinicDoctorPermissionChecker, Clinic, Doctor (+11 more)
Cohesion: 0.05
Nodes (23): ClinicAppointmentAccessTest, ClinicOwnerScheduleAccessTest, ClinicDoctorPermissionTest, ClinicDoctorPermissionRepository, ClinicDoctorPermission, ClinicRecordAccessTest, ClinicDoctorPermissionChecker, Clinic (+15 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (75): grid, PatientFormOptions, patientFormSchema, Props, baseValues, options, setup(), latinDigitsField() (+67 more)
Nodes (69): ServiceItemFormModal(), latinDigitsField(), numericField(), NumericFieldProps, wrap(), iranMobileSchema, CitiesTab(), CityForm (+61 more)
### Community 2 - "Community 2"
Cohesion: 0.10
@@ -1074,12 +1075,12 @@ Cohesion: 0.17
Nodes (8): SettlementController, SettlementRepository, Settlement, JsonResponse, Request, User, ManagerRegistry, User
### Community 7 - "Community 7"
Cohesion: 0.06
Nodes (8): DoctorService, Clinic, DoctorServiceRepository, Collection, Doctor, self, User, ManagerRegistry
Cohesion: 0.05
Nodes (11): DoctorServiceController, DoctorService, Clinic, DoctorServiceRepository, Collection, Doctor, self, User (+3 more)
### Community 8 - "Community 8"
Cohesion: 0.03
Nodes (80): AppointmentLike, ConfirmAppointmentModal(), METHOD_OPTIONS, Props, rowStyle, ServiceItem, STATE_TONE, AppointmentInfoModal() (+72 more)
Nodes (111): AppointmentLike, ConfirmAppointmentModal(), METHOD_OPTIONS, Props, rowStyle, ServiceItem, STATE_TONE, AppointmentInfoModal() (+103 more)
### Community 9 - "Community 9"
Cohesion: 0.04
@@ -1099,19 +1100,19 @@ Nodes (49): Account provisioning, Clinic Doctor Invitation API, Console: `app:in
### Community 13 - "Community 13"
Cohesion: 0.02
Nodes (148): appointment, render(), appt, get, openMenu(), patch, get, Pricing (+140 more)
Nodes (146): appointment, render(), appt, get, openMenu(), patch, ClinicDoctorItem, get (+138 more)
### Community 14 - "Community 14"
Cohesion: 0.09
Nodes (20): EntityContextResolver, AppointmentSettingsController, DateOverride, EntityContext, Holiday, DateOverrideRepository, HolidayRepository, Clinic (+12 more)
### Community 15 - "Community 15"
Cohesion: 0.05
Nodes (20): PaymentController, DomainContextResolver, LogPruneService, MaintenanceService, DomainCommissionTest, MaintenanceService, SubscriptionService, MaintenanceModeTest (+12 more)
Cohesion: 0.25
Nodes (7): PaymentController, Appointment, JsonResponse, Payment, Request, Response, User
### Community 16 - "Community 16"
Cohesion: 0.04
Nodes (13): AppointmentCreateReserveTest, PatientSession, SmsWallet, AppLog, SecretaryAppointmentScopeTest, Appointment, Collection, InventoryPackage (+5 more)
Nodes (11): PatientSession, SmsWallet, SecretaryAppointmentScopeTest, Appointment, Collection, InventoryPackage, PatientRecord, self (+3 more)
### Community 17 - "Community 17"
Cohesion: 0.05
@@ -1130,12 +1131,12 @@ Cohesion: 0.12
Nodes (5): AdminApiController, RepresentationRepository, JsonResponse, Request, StreamedResponse
### Community 21 - "Community 21"
Cohesion: 0.02
Nodes (110): FreeVisitPrice(), Invoice, InvoiceItem, InvoiceSummaryModal(), SessionConsumable, SessionData, SessionPayment, STATUS_LABEL (+102 more)
Cohesion: 0.03
Nodes (74): PatientTagsCell(), TenantTag, TauriStatCards(), PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), AddPackageModal(), formatNumber() (+66 more)
### Community 22 - "Community 22"
Cohesion: 0.15
Nodes (9): RatingController, Like, LikeRepository, JsonResponse, Request, User, Comment, ManagerRegistry (+1 more)
Cohesion: 0.29
Nodes (4): RatingController, JsonResponse, Request, User
### Community 23 - "Community 23"
Cohesion: 0.05
@@ -1154,8 +1155,8 @@ Cohesion: 0.24
Nodes (5): InsuranceController, EntityInsurancePricing, JsonResponse, Request, User
### Community 27 - "Community 27"
Cohesion: 0.06
Nodes (35): 55. 🟢 `GET` all tag, 56. 🟢 `GET` supplementary_insurance, 57. 🟢 `GET` categories list, 58. 🟢 `GET` all state, 59. 🟢 `GET` all city, 60. 🟢 `GET` all specially doctor, 61. 🔵 `POST` post, 63. 🔴 `DELETE` DELETE (+27 more)
Cohesion: 0.05
Nodes (40): 55. 🟢 `GET` all tag, 56. 🟢 `GET` supplementary_insurance, 57. 🟢 `GET` categories list, 58. 🟢 `GET` all state, 59. 🟢 `GET` all city, 60. 🟢 `GET` all specially doctor, 61. 🔵 `POST` post, 62. 🟡 `PATCH` patch (+32 more)
### Community 28 - "Community 28"
Cohesion: 0.06
@@ -1178,8 +1179,8 @@ Cohesion: 0.06
Nodes (32): 10. Modal / Dialog, 11. Toast Notifications, 12. Empty States & Loading, 13. Page Header (هر صفحه), 14. تکنولوژی Stack, 15. Responsive Breakpoints, 16. Dark Mode (اختیاری — فاز دوم), 17. نمونه رنگ‌بندی صفحه داشبورد (+24 more)
### Community 33 - "Community 33"
Cohesion: 0.17
Nodes (9): AbstractAuthenticator, AuthenticationException, ExceptionSubscriber, Passport, PasswordAuthenticator, Request, Response, ExceptionEvent (+1 more)
Cohesion: 0.27
Nodes (7): AbstractAuthenticator, AuthenticationException, Passport, PasswordAuthenticator, Request, Response, TokenInterface
### Community 34 - "Community 34"
Cohesion: 0.05
@@ -1243,7 +1244,7 @@ Nodes (4): Payment, Appointment, self, User
### Community 49 - "Community 49"
Cohesion: 0.07
Nodes (33): ClinicDoctorItem, ClinicDoctorsManager(), ClinicInvitation, HUES_LIST, INV_STATUS_MAP, buildInsurancePayload(), Contract, contractToForm() (+25 more)
Nodes (32): ClinicDoctorsManager(), ClinicInvitation, HUES_LIST, INV_STATUS_MAP, buildInsurancePayload(), Contract, contractToForm(), EMPTY_FORM (+24 more)
### Community 50 - "Community 50"
Cohesion: 0.07
@@ -1259,7 +1260,7 @@ Nodes (26): الزامات UI, باگ‌فیکس صفحه نوبت‌ها, با
### Community 53 - "Community 53"
Cohesion: 0.06
Nodes (20): AppLogRepository, ClaimItemRepository, DoctorClaimRequestRepository, InvoiceItemRepository, PreRegistrationRepository, SessionAuditLogRepository, SiteConfigRepository, TagRepository (+12 more)
Nodes (20): AppLogRepository, ClaimItemRepository, DoctorClaimRequestRepository, DoctorInsuranceRepository, PreRegistrationRepository, SessionAuditLogRepository, SiteConfigRepository, SmsTemplateRepository (+12 more)
### Community 54 - "Community 54"
Cohesion: 0.10
@@ -1282,8 +1283,8 @@ Cohesion: 0.29
Nodes (5): BlogController, City, JsonResponse, Request, User
### Community 59 - "Community 59"
Cohesion: 0.22
Nodes (6): ClinicController, Clinic, DoctorAddress, JsonResponse, Request, User
Cohesion: 0.07
Nodes (14): ClinicController, SpecialtyController, DoctorSpecialtyParentsTest, Specialty, SpecialtyRepository, Clinic, DoctorAddress, JsonResponse (+6 more)
### Community 60 - "Community 60"
Cohesion: 0.08
@@ -1294,12 +1295,12 @@ Cohesion: 0.17
Nodes (12): Add Session Payment (تسویه چندتکه), Create Patient Record, Create Session, Edit Session Payment, Endpoints, Get Patient Record, List Patient Appointments, List Patient Sessions (+4 more)
### Community 62 - "Community 62"
Cohesion: 0.09
Nodes (27): MethodOption, Props, QUICK_TOMANS, WalletModalSubmit, WalletMode, WalletTransactionModal(), BANK_KEY, BankAccount (+19 more)
Cohesion: 0.11
Nodes (21): WalletTransactionModal(), BANK_KEY, BankAccount, BankAccountInput, Pos, POS_KEY, PosInput, useBankAccounts() (+13 more)
### Community 63 - "Community 63"
Cohesion: 0.02
Nodes (151): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, usePermissions(), PaginatedResponse (+143 more)
Nodes (130): PaginatedResponse, formatDate(), formatDateTime(), toDate(), ALL_STATUSES, AppointmentDetailPage(), isoDay(), timeOf() (+122 more)
### Community 64 - "Community 64"
Cohesion: 0.19
@@ -1330,8 +1331,8 @@ Cohesion: 0.08
Nodes (24): سناریو: ایمپورت پزشکان سازمان نظام پزشکی و مدیریت مالکیت پروفایل, نتیجه‌گیری کلیدی طراحی, ۱. خلاصه اجرایی, ۱۰. جریان کاربری (خلاصه‌ی گام‌به‌گام), ۱۱. حالات مرزی و قواعد کسب‌وکار, ۱۲. مراحل پیاده‌سازی (به‌ترتیب و به‌تفکیک ریپو), ۱۳. تصمیمات باز و ریسک‌ها, ۱۴. مرجع نمونه‌ی داده (+16 more)
### Community 72 - "Community 72"
Cohesion: 0.08
Nodes (3): Claim, Collection, self
Cohesion: 0.07
Nodes (4): ClaimItem, Claim, Collection, self
### Community 74 - "Community 74"
Cohesion: 0.09
@@ -1358,8 +1359,8 @@ Cohesion: 0.12
Nodes (3): SubscriptionPlan, Collection, self
### Community 81 - "Community 81"
Cohesion: 0.09
Nodes (23): dependencies, @ckeditor/ckeditor5-build-classic, @ckeditor/ckeditor5-react, @fontsource/vazirmatn, @heroicons/react, @hookform/resolvers, jalaali-js, leaflet (+15 more)
Cohesion: 0.07
Nodes (27): dependencies, @ckeditor/ckeditor5-build-classic, @ckeditor/ckeditor5-react, @fontsource/vazirmatn, @heroicons/react, @hookform/resolvers, jalaali-js, leaflet (+19 more)
### Community 83 - "Community 83"
Cohesion: 0.09
@@ -1374,8 +1375,8 @@ Cohesion: 0.07
Nodes (30): devDependencies, @babel/core, @babel/preset-env, @babel/preset-react, @babel/preset-typescript, core-js, @csstools/postcss-oklab-function, @hotwired/stimulus (+22 more)
### Community 86 - "Community 86"
Cohesion: 0.02
Nodes (29): AppointmentExpiryServiceTest, BookingModeImmutableTest, BookingServicesPublicTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, CaptchaFlowTest, CreateClinicValidationTest (+21 more)
Cohesion: 0.03
Nodes (27): AppointmentExpiryServiceTest, BookingServicesPublicTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListNPlusOneTest, ClaimsListPaginationTest, CaptchaFlowTest, ServiceItemDeleteCleanupTest (+19 more)
### Community 87 - "Community 87"
Cohesion: 0.10
@@ -1446,8 +1447,8 @@ Cohesion: 0.11
Nodes (18): `AdminApiController::paymentDetail` — الان فقط GET, `MellatGateway.php` — الگوی موجود REST/SOAP (پس از کار sandbox), `PaymentGatewayInterface.php`, `PaymentManager.php` — الگوی log و transaction, برگشت/استرداد وجه ملت از پنل ادمین (bpReversalRequest / bpRefundRequest), زمینه, فایل‌های مرتبط, نکات مهم (+10 more)
### Community 104 - "Community 104"
Cohesion: 0.35
Nodes (3): TagController, JsonResponse, Request
Cohesion: 0.18
Nodes (6): TagController, TagRepository, JsonResponse, Request, ManagerRegistry, Tag
### Community 105 - "Community 105"
Cohesion: 0.11
@@ -1462,8 +1463,8 @@ Cohesion: 0.24
Nodes (8): AppointmentController, Appointment, Clinic, Doctor, JsonResponse, Request, User, WeeklySchedule
### Community 108 - "Community 108"
Cohesion: 0.11
Nodes (13): CaptchaController, BaseController, CategoryController, DoctorImportController, SiteContextController, JsonResponse, JsonResponse, Request (+5 more)
Cohesion: 0.09
Nodes (16): CaptchaController, BaseController, CategoryController, CategoryImportController, DoctorImportController, SiteContextController, JsonResponse, JsonResponse (+8 more)
### Community 109 - "Community 109"
Cohesion: 0.29
@@ -1534,8 +1535,8 @@ Cohesion: 0.17
Nodes (4): Rate, Doctor, self, User
### Community 126 - "Community 126"
Cohesion: 0.17
Nodes (9): FormValues, schema, SectionDef, SectionId, SECTIONS, Settings, SettingsPage(), TaxHistoryRow (+1 more)
Cohesion: 0.07
Nodes (17): DEGREE_OPTIONS, DoctorFormPage(), FormValues, GENDER_OPTIONS, schema, SelectedEntry, SpecialtyOption, Breakdown (+9 more)
### Community 128 - "Community 128"
Cohesion: 0.11
@@ -1698,8 +1699,8 @@ Cohesion: 0.10
Nodes (20): api.ir (استعلام هویت — Shahkar / IbanMatch), اتصال به دیتابیس‌های مستقل (الزامی), اسرار (الزامی — قبل از اولین دیپلوی), امنیت و منابع, بررسی سلامت, دامنه‌ها و CORS, دیپلوی‌های بعدی, راهنمای دیپلوی ClinicPro (Coolify + Docker Compose) (+12 more)
### Community 169 - "Community 169"
Cohesion: 0.12
Nodes (8): SourceProfileIdTest, MellatGatewayTest, ErrorCodesTest, TimezoneTest, ActivateTrialTest, SubscriptionService, TestCase, SubscriptionPlan
Cohesion: 0.09
Nodes (10): SourceProfileIdTest, MellatGatewayTest, ErrorCodesTest, HealthControllerTest, TimezoneTest, ActivateTrialTest, SubscriptionService, TestCase (+2 more)
### Community 170 - "Community 170"
Cohesion: 0.13
@@ -1818,12 +1819,12 @@ Cohesion: 0.14
Nodes (13): Endpoint ها, PATCH /api/v1/secretary/{uuid}, POST /api/v1/secretary, تسک ۱۴: ماژول منشی, توضیح, زمان تخمینی, ساختار JSON, سیستم مجوزها — Resource-Based Permissions (مقیاس‌پذیر) (+5 more)
### Community 200 - "Community 200"
Cohesion: 0.03
Nodes (56): DoctorTab, PickedService, ServicePick, ServiceSlot, ServiceSlotPicker(), get, services, td (+48 more)
Cohesion: 0.04
Nodes (42): DoctorTab, PickedService, ServicePick, ServiceSlot, ServiceSlotPicker(), get, services, td (+34 more)
### Community 201 - "Community 201"
Cohesion: 0.11
Nodes (19): Admin API, Behaviour while enabled, Clinic Invitation Management, Console escape hatch, Failure behaviour, GET `/api/v1/admin/pre-registrations`, GET `/api/v1/admin/secretaries`, GET /api/v1/admin/settings (+11 more)
Cohesion: 0.13
Nodes (15): Admin API, Behaviour while enabled, Clinic Invitation Management, Console escape hatch, Failure behaviour, GET `/api/v1/admin/secretaries`, GET /api/v1/admin/settings, Maintenance Mode (+7 more)
### Community 202 - "Community 202"
Cohesion: 0.07
@@ -1834,8 +1835,8 @@ Cohesion: 0.12
Nodes (16): Clinic Services API, DELETE /api/v1/service-item/{uuid}, DELETE /api/v1/service-section/{uuid}, GET /api/v1/service-item/{uuid}, GET /api/v1/service-item/{uuid}/audit-logs, GET /api/v1/service-items, GET /api/v1/service-items/{sectionUuid}, GET /api/v1/service-items/{uuid}/tariffs (+8 more)
### Community 204 - "Community 204"
Cohesion: 0.07
Nodes (35): useSubscription(), AdminLayout(), avatarBg(), HUES, ProfileMenu(), Role, ROLE_LABELS, settingsPath() (+27 more)
Cohesion: 0.04
Nodes (46): RoleRoute(), usePermissions(), useSubscription(), AdminLayout(), avatarBg(), HUES, ProfileMenu(), Role (+38 more)
### Community 205 - "Community 205"
Cohesion: 0.21
@@ -1915,11 +1916,11 @@ Nodes (52): Bulk import / export, DELETE `/api/v1/admin/insurance/{id}`, DELETE
### Community 229 - "Community 229"
Cohesion: 0.14
Nodes (13): DELETE `/api/v1/representation/{uuid}`, Errors, Errors, GET `/api/v1/representation/{uuid}/dashboard/monthly`, GET `/api/v1/site-context`, Path Parameters, Query Parameters, Query Parameters (+5 more)
Nodes (13): Errors, GET `/api/v1/representation/{uuid}/dashboard/monthly`, GET `/api/v1/representation/{uuid}/dashboard/yearly`, GET `/api/v1/site-context`, Path Parameters, Query Parameters, Query Parameters, Query Parameters (+5 more)
### Community 230 - "Community 230"
Cohesion: 0.06
Nodes (30): AdminCharts, AdminDashboard(), AdminRecent, AdminStats, APPT_CLS, APPT_COLOR, APPT_LABEL, ApptRow (+22 more)
Cohesion: 0.05
Nodes (31): ApiAppointment, NOT_VISITED_STATUSES, ServiceOption, STATUS_OPTIONS, NewAppointmentsTable(), AdminCharts, AdminDashboard(), AdminRecent (+23 more)
### Community 231 - "Community 231"
Cohesion: 0.17
@@ -2130,8 +2131,8 @@ Cohesion: 0.19
Nodes (4): ServiceItemRepository, ManagerRegistry, ServiceItem, ServiceSection
### Community 286 - "Community 286"
Cohesion: 0.11
Nodes (11): ChevronDownIcon(), ApptRow, HEAD, NewAppointmentsTable(), Props, JALALI_MONTHS, MONTH_OPTIONS, SelectorOption (+3 more)
Cohesion: 0.20
Nodes (7): ApptRow, JALALI_MONTHS, MONTH_OPTIONS, SelectorOption, TauriDashboardView(), TauriDashboardViewProps, DashboardStats
### Community 287 - "Community 287"
Cohesion: 0.27
@@ -2174,8 +2175,8 @@ Cohesion: 0.22
Nodes (9): Clinic Management, DELETE `/api/v1/admin/clinic/{uuid}`, Errors, GET `/api/v1/admin/clinics`, PATCH `/api/v1/admin/clinic/{uuid}/status`, Query Parameters, Response `200`, Response `200` (+1 more)
### Community 297 - "Community 297"
Cohesion: 0.22
Nodes (9): DELETE `/api/v1/representation/iban/{id}`, Errors, Errors, GET `/api/v1/representation/doctors/stats`, GET `/api/v1/representation/me`, Response `200`, Response `200`, Response `200` (+1 more)
Cohesion: 0.15
Nodes (13): DELETE `/api/v1/representation/iban/{id}`, Errors, Errors, Errors, GET `/api/v1/representation/doctors`, GET `/api/v1/representation/doctors/stats`, GET `/api/v1/representation/me`, Query Parameters (+5 more)
### Community 298 - "Community 298"
Cohesion: 0.22
@@ -2202,8 +2203,8 @@ Cohesion: 0.12
Nodes (16): آماده‌سازی پروژه ClinicPro برای دیپلوی روی Coolify با Docker Compose, زمینه, فایل‌های مرتبط, نکات مهم (محدودیت‌ها و edge caseها), هدف, وظایف, ۱. ساخت `Dockerfile` چندمرحله‌ای, ۱۰. ساخت راهنمای `docs/deploy/coolify.md` (+8 more)
### Community 304 - "Community 304"
Cohesion: 0.22
Nodes (9): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 36. 🟢 `GET` get my rate, 6. کلینیک (Clinic), هدرهای اضافی, پارامترهای Query, پاسخ‌ها, پاسخ‌ها (+1 more)
Cohesion: 0.04
Nodes (52): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 31. 🟡 `PATCH` patch, 33. 🔵 `POST` image_clinic, 34. 🔵 `POST` image logo, 36. 🟢 `GET` get my rate, 37. 🔵 `POST` post, 39. 🟡 `PATCH` Comment confirmation (+44 more)
### Community 306 - "Community 306"
Cohesion: 0.07
@@ -2239,7 +2240,7 @@ Nodes (4): InsuranceRepository, Insurance, InsuranceType, ManagerRegistry
### Community 314 - "Community 314"
Cohesion: 0.02
Nodes (103): AppointmentCardData, AppointmentTurnCard(), base, Breadcrumb(), PatientCaseBanner(), Tag, SessionPaymentAccordion(), SessionPaymentData (+95 more)
Nodes (109): AppointmentCardData, AppointmentTurnCard(), base, Invoice, InvoiceItem, InvoiceSummaryModal(), SessionConsumable, SessionData (+101 more)
### Community 315 - "Community 315"
Cohesion: 0.20
@@ -2249,10 +2250,6 @@ Nodes (6): AuthController, RateLimiterFactory, ClinicDoctorPermission, JsonRespo
Cohesion: 0.12
Nodes (15): mapping صفحات clinicpro → فریم فیگما, الف-۱. توکن‌های رنگ (light + dark), الف-۲. سلکتور رنگ کاربر, الف-۳. ابعاد و رفتار layout, الف-۴. شعاع‌ها و input/button, الف-۵. کامپوننت‌های مشترک مطابق فیگما, ایندکس فریم‌های فیگما (۴ section، node-id دسکتاپ), بخش الف — سیستم طراحی مشترک (یک‌بار، پایه‌ی همه‌ی صفحات) (+7 more)
### Community 317 - "Community 317"
Cohesion: 0.29
Nodes (3): CorsRegexEnvProcessor, EnvVarProcessorInterface, CorsRegexEnvProcessorTest
### Community 318 - "Community 318"
Cohesion: 0.32
Nodes (4): PatientListFilterTest, Doctor, PatientRecord, TenantTag
@@ -2302,8 +2299,8 @@ Cohesion: 0.22
Nodes (8): Query های جدید, بیماران منحصربه‌فرد در بازه, درآمد بر اساس روز (از patient_sessions), فروش اشتراک بر اساس پنل (admin), نوبت‌ها بر اساس روز (admin chart), نکات مهم, هیچ migration لازم نیست, پایگاه داده — تسک ۱۶: داشبورد هوشمند
### Community 333 - "Community 333"
Cohesion: 0.04
Nodes (47): `city` / `state` در پاسخ لیست, DELETE `/api/v1/clinic-pro/doctor-address/{id}`, DELETE `/api/v1/doctor/{uuid}`, Doctor API, Errors, Errors, Errors, Errors (+39 more)
Cohesion: 0.29
Nodes (7): DELETE `/api/v1/clinic-pro/doctor-address/{id}`, Doctor API, Errors, GET `/api/v1/clinic-pro/doctor-addresses/{doctorId}`, Path Parameters, Response `200`, Response `200`
### Community 334 - "Community 334"
Cohesion: 0.25
@@ -2578,8 +2575,8 @@ Cohesion: 0.10
Nodes (20): edge cases, خلاصهٔ خطاها و اولویت, راه‌حل, راه‌حل, راه‌حل, راه‌حل, رفع خطاهای لاگ سرور (production) — ۱۴۰۵/۰۴/۲۰, ریشه (+12 more)
### Community 416 - "Community 416"
Cohesion: 0.08
Nodes (30): EMPTY_CATS, EMPTY_ITEMS, EMPTY_META, EMPTY_PACKAGES, EMPTY_STATS, InventoryItem, InventoryMeta, InventoryPackage (+22 more)
Cohesion: 0.09
Nodes (26): EMPTY_CATS, EMPTY_ITEMS, EMPTY_META, EMPTY_PACKAGES, EMPTY_STATS, InventoryItem, InventoryMeta, InventoryPackage (+18 more)
### Community 418 - "Community 418"
Cohesion: 0.17
@@ -2610,16 +2607,16 @@ Cohesion: 0.18
Nodes (8): ErrorCodes, PatientController, JsonResponse, PatientRecord, PatientRecordScope, PatientSession, Request, User
### Community 435 - "Community 435"
Cohesion: 0.08
Nodes (19): Command, BackfillAppointmentSessionsCommand, CancelExpiredAppointmentsCommand, CreateAdminCommand, MaintenanceCommand, RepairImportedDoctorsCommand, SeedCategoriesCommand, InputInterface (+11 more)
Cohesion: 0.15
Nodes (10): Command, AuditScheduleLocationsCommand, RepairImportedDoctorsCommand, SeedCategoriesCommand, InputInterface, OutputInterface, InputInterface, OutputInterface (+2 more)
### Community 436 - "Community 436"
Cohesion: 0.12
Nodes (16): `book()` عمومی — الگوی درستِ موجود (کپی از `AppointmentController::book`, خط ۲۴۲–۲۶۳), زمینه, فایل‌های مرتبط, فرم — بدون فیلد کد ملی (کپی از `AppointmentCreatePage.tsx`), مسیر ادمین — بیمار فقط با موبایل (کپی از `MyAppointmentsController::createAppointment`, خط ۸۱–۸۷), نوبت‌دهی ادمین بر اساس کد ملی + موبایل (پرونده یکتا با کد ملی), نکات مهم, هدف (+8 more)
### Community 437 - "Community 437"
Cohesion: 0.11
Nodes (12): AdminCspSubscriber, MaintenanceSubscriber, NumericFieldNormalizerSubscriber, SecurityHeadersSubscriber, EventSubscriberInterface, ResponseEvent, ExceptionEvent, Request (+4 more)
Cohesion: 0.09
Nodes (14): AdminCspSubscriber, ExceptionSubscriber, MaintenanceSubscriber, NumericFieldNormalizerSubscriber, SecurityHeadersSubscriber, EventSubscriberInterface, ResponseEvent, ExceptionEvent (+6 more)
### Community 438 - "Community 438"
Cohesion: 0.26
@@ -2754,7 +2751,7 @@ Cohesion: 0.10
Nodes (20): book() فعلی فقط slot_start/slot_end می‌گیرد, overlap واقعی از قبل درست است, زمینه, ساخت اسلاتِ ثابت (حالت فعلی = slot mode), فایل‌های مرتبط, متای برنامهٔ هفتگی, مدت خدمت — هست ولی استفاده نمی‌شود, نوبت‌دهی بر اساس مدت سرویس (Service-based booking) — Backend + Admin (+12 more)
### Community 479 - "Community 479"
Cohesion: 0.16
Cohesion: 0.14
Nodes (6): Authentication, ClinicPro — API Documentation Index, Error Code Reference, Modules, Persian digit normalization (global), Standard Response Envelope
### Community 481 - "Community 481"
@@ -2790,8 +2787,8 @@ Cohesion: 0.20
Nodes (9): Backend Audit Backlog — ClinicPro, ☐ CRITICAL, ✅ DONE (committed on backend-audit), ☐ EPICS (design debt — cross-repo, defer; do NOT quick-fix), ☐ HIGH, ☐ LOW, ☐ MEDIUM, Progress (this audit session) (+1 more)
### Community 494 - "Community 494"
Cohesion: 0.07
Nodes (19): ClaimAmountBoundsTest, ClaimsByPatientTest, ClaimsListNPlusOneTest, ClaimItem, ClaimSubmitterInterface, ClaimService, ManualClaimSubmitter, Claim (+11 more)
Cohesion: 0.24
Nodes (8): ClaimSubmitterInterface, ClaimService, ManualClaimSubmitter, Claim, Invoice, User, Claim, ClaimSubmissionResult
### Community 495 - "Community 495"
Cohesion: 0.12
@@ -2922,8 +2919,8 @@ Cohesion: 0.16
Nodes (3): BankAccount, self, User
### Community 533 - "Community 533"
Cohesion: 0.31
Nodes (4): BaseKernel, Closure, MicroKernelTrait, Kernel
Cohesion: 0.19
Nodes (6): BaseKernel, Closure, CorsRegexEnvProcessor, EnvVarProcessorInterface, MicroKernelTrait, Kernel
### Community 534 - "Community 534"
Cohesion: 0.34
@@ -3018,8 +3015,8 @@ Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/admin/sms/template/{uuid}/reject`, Request Body, Response `200`
### Community 559 - "Community 559"
Cohesion: 0.16
Nodes (7): SmsMessageController, SmsMessageTemplateRepository, SmsTextResolver, SmsMessageTemplate, JsonResponse, Request, ManagerRegistry
Cohesion: 0.25
Nodes (4): SmsMessageTemplateRepository, SmsTextResolver, SmsMessageTemplate, ManagerRegistry
### Community 560 - "Community 560"
Cohesion: 0.50
@@ -3070,8 +3067,8 @@ Cohesion: 0.25
Nodes (8): ۲.۲ انواع دسته‌بندی (Category Types), ۲.۲.۱ تگ (Tag), ۲.۲.۲ استان (State), ۲.۲.۳ شهر (City), ۲.۲.۴ بیمه پایه (Basic Insurance), ۲.۲.۵ بیمه مکمل (Supplementary Insurance), ۲.۲.۶ تخصص دکتر (Doctor Specialty), ۲.۲.۷ خدمات دکتر (Doctor Services)
### Community 577 - "Community 577"
Cohesion: 0.09
Nodes (32): PatientFormValues, dateStrToTs(), EDUCATION_OPTS, formValuesToPayload(), GENDER_OPTS, MARITAL_OPTS, profileToFormValues(), REFERRAL_OPTS (+24 more)
Cohesion: 0.07
Nodes (38): PatientFormValues, baseValues, options, setup(), useIssueInvoice(), dateStrToTs(), EDUCATION_OPTS, formValuesToPayload() (+30 more)
### Community 578 - "Community 578"
Cohesion: 0.36
@@ -3162,8 +3159,8 @@ Cohesion: 0.34
Nodes (5): RepresentationController, JsonResponse, Representation, Request, User
### Community 608 - "Community 608"
Cohesion: 0.35
Nodes (4): ClinicOwnerScheduleAccessTest, Clinic, Doctor, DoctorAddress
Cohesion: 0.19
Nodes (4): LogPruneService, MaintenanceService, MaintenanceModeTest, SiteConfigRepository
### Community 612 - "Community 612"
Cohesion: 0.67
@@ -3197,8 +3194,12 @@ Nodes (16): Runbook — تشخیص «ری‌استارت» سرور: recycle ع
Cohesion: 0.49
Nodes (3): WalletService, User, WalletTransaction
### Community 641 - "Community 641"
Cohesion: 0.22
Nodes (5): ClaimsByPatientTest, Doctor, Invoice, PatientRecord, User
### Community 646 - "Community 646"
Cohesion: 0.12
Cohesion: 0.13
Nodes (3): NumericFieldNormalizerTest, PersianTextTest, PersianText
### Community 647 - "Community 647"
@@ -3222,8 +3223,8 @@ Cohesion: 0.19
Nodes (9): DashboardController, IntlCalendar, Clinic, Doctor, DoctorSecretary, JsonResponse, QueryBuilder, Request (+1 more)
### Community 655 - "Community 655"
Cohesion: 0.35
Nodes (5): MyAppointmentsController, Doctor, JsonResponse, Request, User
Cohesion: 0.21
Nodes (6): MyAppointmentsController, InputValidator, Doctor, JsonResponse, Request, User
### Community 656 - "Community 656"
Cohesion: 0.25
@@ -3278,8 +3279,8 @@ Cohesion: 0.31
Nodes (3): InventoryItemRepository, InventoryItem, ManagerRegistry
### Community 681 - "Community 681"
Cohesion: 0.38
Nodes (3): PurgeUnclaimedDoctorsCommandTest, CommandTester, Doctor
Cohesion: 0.15
Nodes (8): PurgeDoctorsCommandTest, PurgeUnclaimedDoctorsCommandTest, RepositoryClassMappingTest, KernelTestCase, DbLoggerTest, CommandTester, CommandTester, Doctor
### Community 683 - "Community 683"
Cohesion: 0.33
@@ -3349,10 +3350,6 @@ Nodes (16): اصلاح منطق بیمه: یک منبع واحد محاسبه ب
Cohesion: 0.50
Nodes (4): Error Codes, POST `/api/v1/user/reset-password`, Request Body, Response `200`
### Community 707 - "Community 707"
Cohesion: 0.16
Nodes (7): AbstractMigration, Schema, Version20260713115316, Schema, Version20260713195434, Schema, Version20260716094319
### Community 708 - "Community 708"
Cohesion: 0.12
Nodes (15): API کامپوننت `SearchableSelect` (مرجع — تغییرش نده), الگوی A — controlled با `value` + `onChange` (بیشترین), الگوی B — گزینه‌های وابسته / disabled, الگوی C — React Hook Form با `register` (خاص — نیازمند Controller), جایگزینی همه‌ی `<select>` بومی پنل ادمین با `SearchableSelect`, زمینه, فایل‌های دارای `<select>` بومی (۱۶ فایل، ~۳۵ مورد), نکات مهم (+7 more)
@@ -3401,10 +3398,18 @@ Nodes (4): Errors, POST `/api/v1/user/login`, Request Body, Response `200`
Cohesion: 0.43
Nodes (3): PatientResolver, User, UserProfile
### Community 730 - "Community 730"
Cohesion: 0.23
Nodes (5): AbstractMigration, Schema, Version20260610103401, Schema, Version20260614182950
### Community 732 - "Community 732"
Cohesion: 0.15
Nodes (12): call siteهای فعلی PersianDateInput (نباید تغییر کنند — فقط برای اطمینان از سازگاری Props), زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, همه‌ی تقویم‌های پنل ادمین باید شمسی باشند (رفع تقویم میلادی PersianDateInput), وضعیت فعلی (کد مشکل‌دار), وظایف (+4 more)
### Community 733 - "Community 733"
Cohesion: 0.19
Nodes (5): UniqueConstraintsTest, FinancialBreakdown, FinancialBreakdownRepository, ManagerRegistry, Payment
### Community 737 - "Community 737"
Cohesion: 0.38
Nodes (3): PurgeDoctorsCommand, InputInterface, OutputInterface
@@ -3466,8 +3471,8 @@ Cohesion: 0.39
Nodes (3): ClinicStaffRepository, ClinicStaff, ManagerRegistry
### Community 761 - "Community 761"
Cohesion: 0.18
Nodes (9): AdminUser, ASSIGNABLE_ROLES, ChangeRoleModal(), getPrimaryRole(), HUES_LIST, ROLE_META, ROLE_TABS, RoleBadge() (+1 more)
Cohesion: 0.28
Nodes (4): SubscriptionService, ClinicSubscription, Payment, SubscriptionPlan
### Community 763 - "Community 763"
Cohesion: 0.33
@@ -3526,8 +3531,8 @@ Cohesion: 0.24
Nodes (4): InventoryPackageItem, InventoryItem, InventoryPackage, self
### Community 782 - "Community 782"
Cohesion: 0.21
Nodes (7): FinancialBreakdown, FinancialBreakdownRepository, CommissionService, ManagerRegistry, Payment, Payment, Representation
Cohesion: 0.47
Nodes (3): CommissionService, Payment, Representation
### Community 783 - "Community 783"
Cohesion: 0.13
@@ -3546,8 +3551,8 @@ Cohesion: 0.50
Nodes (4): Errors, GET `/oauth/userinfo`, Headers, Response `200`
### Community 789 - "Community 789"
Cohesion: 0.16
Nodes (4): RanginehProvider, SmsService, SendSmsMessage, SmsProviderInterface
Cohesion: 0.12
Nodes (5): KavehNegarProvider, RanginehProvider, SmsService, SendSmsMessage, SmsProviderInterface
### Community 791 - "Community 791"
Cohesion: 0.40
@@ -3594,8 +3599,8 @@ Cohesion: 0.25
Nodes (8): Errors, GET `/api/v1/patient/{uuid}/payments`, GET `/api/v1/patient/{uuid}/wallet`, GET `/api/v1/patient/{uuid}/wallet/transactions`, PATCH `/api/v1/session/{uuid}` — پرداخت مراجعه از کیف پول, POST `/api/v1/patient/{uuid}/wallet/charge`, POST `/api/v1/patient/{uuid}/wallet/withdraw`, مالی بیمار (Financials: پرداخت / تراکنش / کیف‌پول)
### Community 809 - "Community 809"
Cohesion: 0.18
Nodes (4): LoggerInterface, ApiIrService, HealthControllerTest, EntityManagerInterface
Cohesion: 0.13
Nodes (3): LoggerInterface, ApiIrService, MaintenanceService
### Community 810 - "Community 810"
Cohesion: 0.15
@@ -3603,7 +3608,7 @@ Nodes (12): زمینه, فایل‌های مرتبط, مشکل / هدف, نکا
### Community 813 - "Community 813"
Cohesion: 0.17
Nodes (5): BackfillSourceProfileIdStep, SourceProfileId, RepairOptions, RepairResult, SymfonyStyle
Nodes (6): DoctorRepairStep, BackfillSourceProfileIdStep, SourceProfileId, RepairOptions, RepairResult, SymfonyStyle
### Community 814 - "Community 814"
Cohesion: 0.38
@@ -3637,6 +3642,10 @@ Nodes (14): رفع کامل عملیات نوبت در حالت کلینیک (co
Cohesion: 0.50
Nodes (4): autoload, files, psr-4, App\\
### Community 832 - "Community 832"
Cohesion: 0.30
Nodes (4): DomainContextResolver, DomainCommissionTest, Payment, Representation
### Community 833 - "Community 833"
Cohesion: 0.50
Nodes (4): extra, symfony, allow-contrib, require
@@ -3658,16 +3667,16 @@ Cohesion: 0.47
Nodes (3): BookingContextResolver, Clinic, Doctor
### Community 840 - "Community 840"
Cohesion: 0.35
Nodes (3): SpecialtyController, JsonResponse, Request
Cohesion: 0.33
Nodes (5): Like, LikeRepository, Comment, ManagerRegistry, User
### Community 841 - "Community 841"
Cohesion: 0.36
Nodes (3): DoctorServiceController, JsonResponse, Request
Nodes (4): ClaimAmountBoundsTest, Claim, Doctor, User
### Community 842 - "Community 842"
Cohesion: 0.35
Nodes (3): DoctorSpecialtyParentsTest, SpecialtyRepository, Specialty
Cohesion: 0.38
Nodes (3): BackfillAppointmentSessionsCommand, InputInterface, OutputInterface
### Community 844 - "Community 844"
Cohesion: 0.15
@@ -3738,8 +3747,8 @@ Cohesion: 0.36
Nodes (3): TenantTagRepository, ManagerRegistry, TenantTag
### Community 868 - "Community 868"
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/representation/doctors`, Query Parameters, Response `200`
Cohesion: 0.38
Nodes (3): CreateAdminCommand, InputInterface, OutputInterface
### Community 869 - "Community 869"
Cohesion: 0.43
@@ -3770,13 +3779,17 @@ Cohesion: 0.33
Nodes (3): PurgeUnclaimedDoctorsCommand, InputInterface, OutputInterface
### Community 881 - "Community 881"
Cohesion: 0.67
Nodes (3): GET `/api/v1/representation/{uuid}/dashboard/yearly`, Query Parameters, Response `200`
Cohesion: 0.38
Nodes (3): MaintenanceCommand, InputInterface, OutputInterface
### Community 884 - "Community 884"
Cohesion: 0.15
Nodes (12): زمینه, فایل‌های مرتبط, فرآیند ثبت و قطعی کردن نوبت (مودال پرداخت + پرونده), مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, پروژه (+4 more)
### Community 890 - "Community 890"
Cohesion: 0.43
Nodes (3): SmsMessageController, JsonResponse, Request
### Community 899 - "Community 899"
Cohesion: 0.15
Nodes (12): دسترسی پزشک و مدیر کلینیک به پرونده‌های کلینیک, زمینه, فایل‌های مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, پروژه (+4 more)
@@ -3806,8 +3819,8 @@ Cohesion: 0.18
Nodes (10): زمینه, نکات مهم, هدف, وظایف, پاک‌سازی رکوردهای آلودهٔ پزشک و کلینیک, پروژه, ۱. گزارش دامنهٔ آلودگی (اول اندازه‌گیری، بعد حذف), ۲. پاک‌سازی (+2 more)
### Community 908 - "Community 908"
Cohesion: 0.15
Nodes (8): PurgeDoctorsCommandTest, RepairImportedDoctorsCommandTest, RepositoryClassMappingTest, KernelTestCase, DbLoggerTest, CommandTester, CommandTester, Doctor
Cohesion: 0.42
Nodes (3): RepairImportedDoctorsCommandTest, CommandTester, Doctor
### Community 910 - "Community 910"
Cohesion: 0.50
@@ -3825,6 +3838,10 @@ Nodes (6): Errors, GET `/api/v1/clinic/{uuid}`, Path Parameters, Response `200`,
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/admin/clinic/{clinicUuid}/doctor/{doctorUuid}/permissions`, Path Parameters, Response `200`
### Community 914 - "Community 914"
Cohesion: 0.43
Nodes (3): InvoiceItemRepository, InvoiceItem, ManagerRegistry
### Community 915 - "Community 915"
Cohesion: 0.18
Nodes (10): افزودن شهر به لیست پزشکان + رفع سقف خاموش limit, زمینه, فایل‌های مرتبط, نکات مهم, وضعیت فعلی, وظایف, پروژه, ۱. افزودن شهر به `toListArray()` (+2 more)
@@ -3849,9 +3866,9 @@ Nodes (9): Clinic API, Clinic Doctor Permissions, Errors, Errors, GET `/api/v1/a
Cohesion: 0.36
Nodes (4): SiteConfigController, JsonResponse, Request, User
### Community 928 - "Community 928"
Cohesion: 0.43
Nodes (3): SmsTemplateRepository, SmsTemplate, ManagerRegistry
### Community 929 - "Community 929"
Cohesion: 0.33
Nodes (6): `city` / `state` در پاسخ لیست, GET `/api/v1/doctors`, Query Parameters, Response `200`, اعتبارسنجی نام پزشک, مرتب‌سازی و تعریف «دارای نوبت»
### Community 930 - "Community 930"
Cohesion: 0.50
@@ -3869,17 +3886,13 @@ Nodes (3): RepairAcceptedInvitationsCommand, InputInterface, OutputInterface
Cohesion: 0.38
Nodes (3): NormalizeScheduleFormatCommand, InputInterface, OutputInterface
### Community 938 - "Community 938"
Cohesion: 0.43
Nodes (3): CategoryImportController, JsonResponse, Request
### Community 939 - "Community 939"
Cohesion: 0.22
Nodes (5): DoctorRepairStep, BackfillSpecialtyParentsStep, RepairOptions, RepairResult, SymfonyStyle
Cohesion: 0.25
Nodes (4): BackfillSpecialtyParentsStep, RepairOptions, RepairResult, SymfonyStyle
### Community 940 - "Community 940"
Cohesion: 0.48
Nodes (3): DoctorInsuranceRepository, DoctorInsurance, ManagerRegistry
Cohesion: 0.47
Nodes (3): CancelExpiredAppointmentsCommand, InputInterface, OutputInterface
### Community 941 - "Community 941"
Cohesion: 0.25
@@ -3929,10 +3942,6 @@ Nodes (5): Errors, POST `/api/v1/appointment/{uuid}/confirm`, Request Body, Resp
Cohesion: 0.40
Nodes (5): DELETE `/api/v1/patient/attachment/{uuid}`, Errors, GET `/api/v1/patient/{uuid}/attachments`, POST `/api/v1/patient/{uuid}/attachment`, ضمیمه‌های بیمار (Attachments)
### Community 960 - "Community 960"
Cohesion: 0.40
Nodes (5): 37. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 962 - "Community 962"
Cohesion: 0.53
Nodes (3): PaymentLog, PaymentLogRepository, ManagerRegistry
@@ -3978,12 +3987,12 @@ Cohesion: 0.40
Nodes (5): Errors, GET `/api/v1/clinic/my-doctor/{doctorUuid}`, Path Parameters, Response `200`, Schedule Fields Notes
### Community 973 - "Community 973"
Cohesion: 0.39
Nodes (5): CalendarIcon(), CardIcon(), CardTickIcon(), UserAddIcon(), StatCardModel
Cohesion: 0.17
Nodes (8): CalendarIcon(), CardIcon(), CardTickIcon(), ChevronDownIcon(), UserAddIcon(), HEAD, Props, StatCardModel
### Community 974 - "Community 974"
Cohesion: 0.50
Nodes (4): 44. 🟢 `GET` list comment, هدرهای اضافی, پارامترهای Query, پاسخ‌ها
Cohesion: 0.40
Nodes (5): Errors, PATCH `/api/v1/doctor/{uuid}`, Path Parameters, Request Body (`application/json`), Response `200`
### Community 976 - "Community 976"
Cohesion: 0.50
@@ -4006,12 +4015,8 @@ Cohesion: 0.43
Nodes (3): ClaimStatusLog, ClaimStatusLogRepository, ManagerRegistry
### Community 982 - "Community 982"
Cohesion: 0.38
Nodes (3): AuditScheduleLocationsCommand, InputInterface, OutputInterface
### Community 983 - "Community 983"
Cohesion: 0.40
Nodes (5): 62. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
Nodes (5): Errors, PATCH `/api/v1/clinic-pro/doctor-address/{id}`, Path Parameters, Request Body, Response `200`
### Community 985 - "Community 985"
Cohesion: 0.67
@@ -4037,29 +4042,25 @@ Nodes (3): Errors, POST `/api/v1/sms/send` — ⛔ غیرفعال (Deprecated),
Cohesion: 0.47
Nodes (3): SeedSmsMessageTemplatesCommand, InputInterface, OutputInterface
### Community 997 - "Community 997"
Cohesion: 0.67
Nodes (3): 33. 🔵 `POST` image_clinic, هدرهای اضافی, پاسخ‌ها
### Community 999 - "Community 999"
Cohesion: 0.40
Nodes (5): GET `/api/v1/admin/financial-breakdowns`, GET `/api/v1/admin/financial-summary`, GET `/api/v1/admin/settings/tax-history`, GET `/api/v1/admin/settlement/{uuid}`, موتور مالی نمایندگی
### Community 1000 - "Community 1000"
Cohesion: 0.40
Nodes (5): 31. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 1001 - "Community 1001"
Cohesion: 0.40
Nodes (5): 35. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 1002 - "Community 1002"
Cohesion: 0.40
Nodes (5): 41. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/pre-registrations`, POST `/api/v1/admin/pre-registrations/{uuid}/approve`, POST `/api/v1/admin/pre-registrations/{uuid}/reject`, Pre-Registration Management
### Community 1003 - "Community 1003"
Cohesion: 0.40
Nodes (4): license, overrides, lodash, private
Cohesion: 0.50
Nodes (4): DELETE `/api/v1/doctor/{uuid}`, Errors, Path Parameters, Response `200`
### Community 1004 - "Community 1004"
Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/doctor`, Request Body (`application/json`), Response `201`
### Community 1007 - "Community 1007"
Cohesion: 0.50
@@ -4067,7 +4068,7 @@ Nodes (4): 38. 🟢 `GET` Unapproved comments, هدرهای اضافی, پارا
### Community 1008 - "Community 1008"
Cohesion: 0.50
Nodes (4): 39. 🟡 `PATCH` Comment confirmation, مثال Request, هدرهای اضافی, پاسخ‌ها
Nodes (4): Errors, GET `/api/v1/doctor/{uuid}`, Path Parameters, Response `200`
### Community 1009 - "Community 1009"
Cohesion: 0.50
@@ -4075,47 +4076,43 @@ Nodes (4): 40. 🔵 `POST` post, مثال Request, هدرهای اضافی, پا
### Community 1010 - "Community 1010"
Cohesion: 0.50
Nodes (4): 45. 🔵 `POST` post, مثال Request, هدرهای اضافی, پاسخ‌ها
Nodes (4): Errors, POST `/file/upload/clinic_pro/doctor/field_image`, Request, Response `200`
### Community 1011 - "Community 1011"
Cohesion: 0.50
Nodes (4): 46. 🟡 `PATCH` patch, مثال Request, هدرهای اضافی, پاسخ‌ها
Nodes (4): Errors, POST `/api/v1/clinic-pro/doctor-address`, Request Body, Response `201`
### Community 1012 - "Community 1012"
Cohesion: 0.50
Nodes (3): Altcha(), AltchaProps, IntrinsicElements
Cohesion: 0.04
Nodes (40): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), queryClient, toastStyle, DoctorProfilePage(), InsurancePricingPage(), ForgotStep (+32 more)
### Community 1013 - "Community 1013"
Cohesion: 0.67
Nodes (3): 34. 🔵 `POST` image logo, هدرهای اضافی, پاسخ‌ها
Cohesion: 0.50
Nodes (4): Errors, Path Parameters, POST `/api/v1/clinic-pro/doctor-address/from-clinic/{clinicUuid}`, Response `201`
### Community 1015 - "Community 1015"
Cohesion: 0.67
Nodes (3): 42. 🔴 `DELETE` delete, هدرهای اضافی, پاسخ‌ها
### Community 1016 - "Community 1016"
Cohesion: 0.67
Nodes (3): 43. 🟢 `GET` get, هدرهای اضافی, پاسخ‌ها
Nodes (3): DELETE `/api/v1/representation/{uuid}`, Errors, Response `200`
## Knowledge Gaps
- **5271 isolated node(s):** `PORT`, `ROLES`, `[cmd, ...argv]`, `positional`, `opts` (+5266 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **237 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **239 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Altcha` connect `Community 367` to `Community 1012`, `Community 485`?**
_High betweenness centrality (0.115) - this node is a cross-community bridge._
- **Why does `SiteConfigRepository` connect `Community 15` to `Community 485`, `Community 809`, `Community 169`, `Community 205`, `Community 206`, `Community 367`, `Community 782`, `Community 637`, `Community 926`?**
_High betweenness centrality (0.104) - this node is a cross-community bridge._
- **Why does `BaseController` connect `Community 108` to `Community 771`, `Community 6`, `Community 265`, `Community 138`, `Community 139`, `Community 14`, `Community 654`, `Community 655`, `Community 529`, `Community 15`, `Community 275`, `Community 20`, `Community 22`, `Community 26`, `Community 926`, `Community 676`, `Community 295`, `Community 938`, `Community 559`, `Community 433`, `Community 689`, `Community 438`, `Community 58`, `Community 59`, `Community 315`, `Community 699`, `Community 444`, `Community 64`, `Community 840`, `Community 841`, `Community 75`, `Community 77`, `Community 607`, `Community 739`, `Community 104`, `Community 873`, `Community 107`, `Community 109`, `Community 245`, `Community 121`, `Community 122`, `Community 252`?**
_High betweenness centrality (0.056) - this node is a cross-community bridge._
- **Why does `SiteConfigRepository` connect `Community 608` to `Community 832`, `Community 485`, `Community 809`, `Community 169`, `Community 205`, `Community 206`, `Community 15`, `Community 367`, `Community 782`, `Community 761`, `Community 637`, `Community 926`?**
_High betweenness centrality (0.103) - this node is a cross-community bridge._
- **Why does `BaseController` connect `Community 108` to `Community 771`, `Community 6`, `Community 7`, `Community 265`, `Community 138`, `Community 139`, `Community 14`, `Community 654`, `Community 655`, `Community 529`, `Community 15`, `Community 275`, `Community 20`, `Community 22`, `Community 26`, `Community 926`, `Community 676`, `Community 295`, `Community 433`, `Community 689`, `Community 438`, `Community 58`, `Community 59`, `Community 315`, `Community 699`, `Community 444`, `Community 64`, `Community 75`, `Community 77`, `Community 607`, `Community 739`, `Community 122`, `Community 104`, `Community 873`, `Community 107`, `Community 109`, `Community 245`, `Community 121`, `Community 890`, `Community 252`?**
_High betweenness centrality (0.057) - this node is a cross-community bridge._
- **What connects `PORT`, `ROLES`, `[cmd, ...argv]` to the rest of the system?**
_5271 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.06073871409028728 - nodes in this community are weakly interconnected._
_Cohesion score 0.05237171574678187 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.025210084033613446 - nodes in this community are weakly interconnected._
_Cohesion score 0.02562342713337909 - nodes in this community are weakly interconnected._
- **Should `Community 2` be split into smaller, more focused modules?**
_Cohesion score 0.09523809523809523 - nodes in this community are weakly interconnected._
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "label": "seed_testdata.php", "file_type": "code", "source_file": "seed_testdata.php", "source_location": "L1"}, {"id": "clinicpro_seed_testdata_makeuser", "label": "makeUser()", "file_type": "code", "source_file": "seed_testdata.php", "source_location": "L29"}, {"id": "user", "label": "User", "file_type": "code", "source_file": "seed_testdata.php", "source_location": "L29"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "user", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "clinic", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L8", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "doctor", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L9", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "doctorsecretary", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L10", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "kernel", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L11", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "dotenv", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L12", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "passwordhasherfactory", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L13", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "userpasswordhasher", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L14", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_seed_testdata_php", "target": "clinicpro_seed_testdata_makeuser", "relation": "contains", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L29", "weight": 1.0}, {"source": "clinicpro_seed_testdata_makeuser", "target": "user", "relation": "references", "confidence": "EXTRACTED", "source_file": "seed_testdata.php", "source_location": "L29", "weight": 1.0, "context": "return_type"}], "raw_calls": [{"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "setPasswordHash", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L32", "receiver": null}, {"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "hashPassword", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L32", "receiver": null}, {"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "setStatus", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L33", "receiver": null}, {"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "setRoles", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L33", "receiver": null}, {"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "setRealName", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L33", "receiver": null}, {"caller_nid": "clinicpro_seed_testdata_makeuser", "callee": "persist", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/seed_testdata.php", "source_location": "L34", "receiver": null}]}
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1563 -1375
View File
File diff suppressed because it is too large Load Diff
+82 -77
View File
@@ -1,6 +1,6 @@
{
"assets/admin/App.tsx": {
"mtime": 1784464897.1725092,
"mtime": 1784800330.867158,
"ast_hash": "44e9c8016ce761134c7358abce0d2335",
"semantic_hash": ""
},
@@ -15,7 +15,7 @@
"semantic_hash": ""
},
"assets/admin/components/TenantInsuranceContracts.tsx": {
"mtime": 1784648543.4462428,
"mtime": 1784727191.1352344,
"ast_hash": "4a42f431d0ec0eb96440521aaa11558f",
"semantic_hash": ""
},
@@ -25,8 +25,8 @@
"semantic_hash": ""
},
"assets/admin/components/layout/Sidebar.tsx": {
"mtime": 1784725036.068207,
"ast_hash": "e9cf550bb66adf2d7fdf9f98d13e6380",
"mtime": 1784806301.3375194,
"ast_hash": "1183af78de88e296068eaded6a211c47",
"semantic_hash": ""
},
"assets/admin/components/layout/Topbar.tsx": {
@@ -170,8 +170,8 @@
"semantic_hash": ""
},
"assets/admin/pages/AppointmentsPage.tsx": {
"mtime": 1784724451.9449,
"ast_hash": "a46c6f04b751afda1b34768ef1594842",
"mtime": 1784806676.9626431,
"ast_hash": "4304e5435b9bfdf9e25efd3271387704",
"semantic_hash": ""
},
"assets/admin/pages/BlogFormPage.tsx": {
@@ -195,7 +195,7 @@
"semantic_hash": ""
},
"assets/admin/pages/ClinicDetailPage.tsx": {
"mtime": 1784464897.2656515,
"mtime": 1784806088.5971308,
"ast_hash": "624530292023fbdac8991cc5b0e91ecd",
"semantic_hash": ""
},
@@ -335,7 +335,7 @@
"semantic_hash": ""
},
"assets/admin/pages/SettingsPage.tsx": {
"mtime": 1784531682.4095857,
"mtime": 1784806088.5979247,
"ast_hash": "3ec0502958ed23ff8d38c859275f0398",
"semantic_hash": ""
},
@@ -790,8 +790,8 @@
"semantic_hash": ""
},
"public/sw.js": {
"mtime": 1781344587.5211058,
"ast_hash": "0adb874e986f07690584a2bbaa7534c6",
"mtime": 1784802929.2984245,
"ast_hash": "c449612287bd2a8852e3fececfc099d0",
"semantic_hash": ""
},
"skills-lock.json": {
@@ -800,7 +800,7 @@
"semantic_hash": ""
},
"src/Admin/Controller/AdminApiController.php": {
"mtime": 1784724432.6225293,
"mtime": 1784727191.2045786,
"ast_hash": "3d17253ef21bf9f6d7b2eacc178336f6",
"semantic_hash": ""
},
@@ -815,7 +815,7 @@
"semantic_hash": ""
},
"src/Appointment/Controller/AppointmentController.php": {
"mtime": 1784724416.5016863,
"mtime": 1784800330.9387112,
"ast_hash": "c9e5bad6526642fd698b24bf6c37d536",
"semantic_hash": ""
},
@@ -825,8 +825,8 @@
"semantic_hash": ""
},
"src/Appointment/Controller/MyAppointmentsController.php": {
"mtime": 1784724427.3881004,
"ast_hash": "fa18d2576dfbf3f6e3d78caf7e2476b4",
"mtime": 1784806547.3188496,
"ast_hash": "b6508c5ee138d8407f339ab6bc4033c6",
"semantic_hash": ""
},
"src/Appointment/Entity/Appointment.php": {
@@ -890,7 +890,7 @@
"semantic_hash": ""
},
"src/Appointment/Service/SlotCalculatorService.php": {
"mtime": 1784724332.9448338,
"mtime": 1784727191.2166848,
"ast_hash": "31ac07294f7d8f10ca46fc296401f86b",
"semantic_hash": ""
},
@@ -990,7 +990,7 @@
"semantic_hash": ""
},
"src/Billing/Entity/InvoiceItem.php": {
"mtime": 1784647364.4653955,
"mtime": 1784800330.9390402,
"ast_hash": "a184b2972d82eb75388867426f39c89b",
"semantic_hash": ""
},
@@ -1015,7 +1015,7 @@
"semantic_hash": ""
},
"src/Billing/Service/BillingCalculator.php": {
"mtime": 1784647364.4656363,
"mtime": 1784800330.9392138,
"ast_hash": "058f6659747066708ad288f663b077a4",
"semantic_hash": ""
},
@@ -1025,7 +1025,7 @@
"semantic_hash": ""
},
"src/Billing/Service/InvoiceService.php": {
"mtime": 1784647364.4659197,
"mtime": 1784800330.9393814,
"ast_hash": "303af7bc3c22e857e9bdba3e35305a2f",
"semantic_hash": ""
},
@@ -1100,12 +1100,12 @@
"semantic_hash": ""
},
"src/ClinicService/Controller/ClinicServiceController.php": {
"mtime": 1784464902.6058023,
"mtime": 1784800330.9396129,
"ast_hash": "6104f39d30ab682b3154be12ecc4dbdd",
"semantic_hash": ""
},
"src/ClinicService/Entity/ServiceItem.php": {
"mtime": 1784464902.6066225,
"mtime": 1784800330.939908,
"ast_hash": "e9cc1907bbfd5105190b6275a2ddd477",
"semantic_hash": ""
},
@@ -1115,7 +1115,7 @@
"semantic_hash": ""
},
"src/ClinicService/Entity/Tariff.php": {
"mtime": 1784647364.466187,
"mtime": 1784800330.9400997,
"ast_hash": "41dc8e6bc415c27895bdb2f19094d1fa",
"semantic_hash": ""
},
@@ -1130,17 +1130,17 @@
"semantic_hash": ""
},
"src/ClinicService/Repository/TariffRepository.php": {
"mtime": 1782214545.7297218,
"mtime": 1784800330.940418,
"ast_hash": "f408ef90e8cf3b698abec3a9b24c110b",
"semantic_hash": ""
},
"src/ClinicService/Service/TariffService.php": {
"mtime": 1784647364.4663801,
"mtime": 1784800330.9405704,
"ast_hash": "1f4632e4fb1e9b48e0d2304f261e01bf",
"semantic_hash": ""
},
"src/Config/Controller/SiteConfigController.php": {
"mtime": 1784531682.4802425,
"mtime": 1784806088.6001577,
"ast_hash": "c38867c348e37537eeab810901a87fd4",
"semantic_hash": ""
},
@@ -1155,7 +1155,7 @@
"semantic_hash": ""
},
"src/Config/Repository/SiteConfigRepository.php": {
"mtime": 1784531682.480537,
"mtime": 1784806088.601283,
"ast_hash": "4727b2669cfec0b1770f898565a836b6",
"semantic_hash": ""
},
@@ -1175,7 +1175,7 @@
"semantic_hash": ""
},
"src/Doctor/Entity/Doctor.php": {
"mtime": 1784482277.7317781,
"mtime": 1784800330.9413614,
"ast_hash": "e0a790cbbdc3e0e12186ebd2a07560a6",
"semantic_hash": ""
},
@@ -1210,7 +1210,7 @@
"semantic_hash": ""
},
"src/Insurance/Controller/InsuranceController.php": {
"mtime": 1784648361.700381,
"mtime": 1784800330.9420345,
"ast_hash": "9e591e5164b5b32c33b7341d6c065c88",
"semantic_hash": ""
},
@@ -1270,12 +1270,12 @@
"semantic_hash": ""
},
"src/Insurance/Service/TenantInsuranceService.php": {
"mtime": 1784647364.4672372,
"mtime": 1784800330.94217,
"ast_hash": "bfcf78e62b19d8da6e04dd52ce7aee08",
"semantic_hash": ""
},
"src/Insurance/ValueObject/CoverageRule.php": {
"mtime": 1784647364.4673338,
"mtime": 1784800330.94226,
"ast_hash": "c698dbdfd800a641f7ebbaf35bccbb22",
"semantic_hash": ""
},
@@ -1310,7 +1310,7 @@
"semantic_hash": ""
},
"src/Patient/Controller/PatientController.php": {
"mtime": 1784464902.6331751,
"mtime": 1784800330.9426308,
"ast_hash": "ee5a2df1047e175fbbe87ba89dcca0ef",
"semantic_hash": ""
},
@@ -1320,7 +1320,7 @@
"semantic_hash": ""
},
"src/Patient/Entity/PatientSession.php": {
"mtime": 1784647364.467601,
"mtime": 1784800330.9427798,
"ast_hash": "a50e1a3314a06db4443974762fc0e284",
"semantic_hash": ""
},
@@ -1345,7 +1345,7 @@
"semantic_hash": ""
},
"src/Patient/Service/PatientService.php": {
"mtime": 1784647364.4679837,
"mtime": 1784800330.943104,
"ast_hash": "996ca5b9d953fa8093c5cbdf8632590c",
"semantic_hash": ""
},
@@ -1800,7 +1800,7 @@
"semantic_hash": ""
},
"tests/Billing/BillingCalculatorTest.php": {
"mtime": 1784647364.468918,
"mtime": 1784800330.9433763,
"ast_hash": "528387e44a3a0e3d22f9d7e3fd7f4919",
"semantic_hash": ""
},
@@ -2245,7 +2245,7 @@
"semantic_hash": ""
},
"config/packages/security.yaml": {
"mtime": 1784724747.852775,
"mtime": 1784727191.139414,
"ast_hash": "5370c5722d3d930250df15eb3e3f0d45",
"semantic_hash": ""
},
@@ -2325,7 +2325,7 @@
"semantic_hash": ""
},
"docs/api/admin.md": {
"mtime": 1784531682.4100816,
"mtime": 1784806088.5987606,
"ast_hash": "bf314171d39c11d73ce605c878ce117b",
"semantic_hash": ""
},
@@ -2335,8 +2335,8 @@
"semantic_hash": ""
},
"docs/api/appointment.md": {
"mtime": 1784724907.243869,
"ast_hash": "35452b90c51a20fbb1f7d3f14ce76918",
"mtime": 1784806823.2681842,
"ast_hash": "f9fc3c259c0609e167fa68c012d7b1fd",
"semantic_hash": ""
},
"docs/api/auth.md": {
@@ -2345,7 +2345,7 @@
"semantic_hash": ""
},
"docs/api/billing.md": {
"mtime": 1784464897.3122041,
"mtime": 1784800330.8696327,
"ast_hash": "08efc312af675bedb01558616d266f39",
"semantic_hash": ""
},
@@ -2360,7 +2360,7 @@
"semantic_hash": ""
},
"docs/api/clinic-services.md": {
"mtime": 1784464897.3139665,
"mtime": 1784800330.86981,
"ast_hash": "41f687c63fd6085797ed5a1501ce78c1",
"semantic_hash": ""
},
@@ -2385,7 +2385,7 @@
"semantic_hash": ""
},
"docs/api/insurance.md": {
"mtime": 1784648669.9362624,
"mtime": 1784800330.8701859,
"ast_hash": "6615b0f1865200d269dee7cb1dab7ad5",
"semantic_hash": ""
},
@@ -2395,7 +2395,7 @@
"semantic_hash": ""
},
"docs/api/patient.md": {
"mtime": 1784647364.4643183,
"mtime": 1784800330.8704922,
"ast_hash": "d0de4655e7a33cb4b9f75c371361670f",
"semantic_hash": ""
},
@@ -3415,7 +3415,7 @@
"semantic_hash": ""
},
"data/seed/cities.json": {
"mtime": 1783788126.5797431,
"mtime": 1784800899.555101,
"ast_hash": "712cdcd70a3de11d2b443c329501e6cf",
"semantic_hash": ""
},
@@ -4070,7 +4070,7 @@
"semantic_hash": ""
},
"assets/admin/components/layout/SettingsLayout.tsx": {
"mtime": 1784464897.2018077,
"mtime": 1784800330.868629,
"ast_hash": "731fb15294fe8b9490a0126e55cb43ab",
"semantic_hash": ""
},
@@ -4130,12 +4130,12 @@
"semantic_hash": ""
},
"assets/admin/pages/AppointmentSettingsPage.test.tsx": {
"mtime": 1784725571.2514737,
"mtime": 1784727191.137884,
"ast_hash": "2fab7355fcf74ac0228377749dccba3f",
"semantic_hash": ""
},
"assets/admin/pages/AppointmentSettingsPage.tsx": {
"mtime": 1784725476.1800926,
"mtime": 1784727191.1386728,
"ast_hash": "3869ca602f2068bc61c835704c8f6040",
"semantic_hash": ""
},
@@ -4355,7 +4355,7 @@
"semantic_hash": ""
},
"assets/admin/components/NewAppointmentDrawer.tsx": {
"mtime": 1784724466.7969532,
"mtime": 1784727191.1345496,
"ast_hash": "a49f947e9fda2acbbd4a470ac2ecac40",
"semantic_hash": ""
},
@@ -4505,7 +4505,7 @@
"semantic_hash": ""
},
"assets/admin/components/InvoiceSummaryModal.tsx": {
"mtime": 1784464897.1774275,
"mtime": 1784800330.8681514,
"ast_hash": "c286824e4f5a0e9f0e5278abc8cb8a6e",
"semantic_hash": ""
},
@@ -4630,12 +4630,12 @@
"semantic_hash": ""
},
"assets/admin/components/InsuranceModal.test.tsx": {
"mtime": 1784464897.1765587,
"mtime": 1784800330.8673258,
"ast_hash": "6722dfa2d7b422b136695333f993b2e2",
"semantic_hash": ""
},
"assets/admin/components/InsuranceModal.tsx": {
"mtime": 1784648479.2794728,
"mtime": 1784800330.8677561,
"ast_hash": "8cb3febb1ad601e108b61d19c6a6e18e",
"semantic_hash": ""
},
@@ -4800,8 +4800,8 @@
"semantic_hash": ""
},
"assets/admin/components/layout/Sidebar.test.tsx": {
"mtime": 1784464897.2020903,
"ast_hash": "18d9c888d8dd85fe56cd8d504eb01d54",
"mtime": 1784806332.1391919,
"ast_hash": "f4f1d6d00ed45ca7875fcd13cba90e82",
"semantic_hash": ""
},
"assets/admin/pages/AppointmentCreatePage.test.tsx": {
@@ -4875,7 +4875,7 @@
"semantic_hash": ""
},
"assets/admin/components/appointments/ServiceSlotPicker.tsx": {
"mtime": 1784724459.444737,
"mtime": 1784727191.1357775,
"ast_hash": "dc7a2d5525f7a454dd89ef0549f3bdbf",
"semantic_hash": ""
},
@@ -4890,8 +4890,8 @@
"semantic_hash": ""
},
"assets/admin/pages/AppointmentBookingModal.test.tsx": {
"mtime": 1784464897.2334166,
"ast_hash": "3a3dfdbcc7405a2898075d80471bfa82",
"mtime": 1784806782.881906,
"ast_hash": "362d4053a7c9d03f58a1f8e498d68f51",
"semantic_hash": ""
},
"config/bootstrap_tz.php": {
@@ -4915,8 +4915,8 @@
"semantic_hash": ""
},
"tests/Appointment/PatientLookupTest.php": {
"mtime": 1784464902.7022443,
"ast_hash": "f64f456662ad3008d7c3875bac3e5057",
"mtime": 1784806722.0397148,
"ast_hash": "e91d8e7484dd15d1c7a9f16b7638956a",
"semantic_hash": ""
},
"tests/Appointment/ServiceBasedSlotsTest.php": {
@@ -5090,7 +5090,7 @@
"semantic_hash": ""
},
"src/Patient/Entity/SessionPayment.php": {
"mtime": 1784464902.6388512,
"mtime": 1784800330.9428656,
"ast_hash": "590d92516877e011b5362e9644d319ba",
"semantic_hash": ""
},
@@ -5100,7 +5100,7 @@
"semantic_hash": ""
},
"tests/Patient/SessionPaymentTest.php": {
"mtime": 1784464902.7555523,
"mtime": 1784800330.94366,
"ast_hash": "2e28dcc5c5b3279db8e05b9e4ba8e11a",
"semantic_hash": ""
},
@@ -5145,7 +5145,7 @@
"semantic_hash": ""
},
"assets/admin/components/InvoiceSummaryModal.test.tsx": {
"mtime": 1784464897.17714,
"mtime": 1784800330.867904,
"ast_hash": "a72d00d8a95f98ab5cf6899631f165c9",
"semantic_hash": ""
},
@@ -5200,7 +5200,7 @@
"semantic_hash": ""
},
"assets/admin/components/schedule/ScheduleSection.tsx": {
"mtime": 1784725332.9969523,
"mtime": 1784727191.1370828,
"ast_hash": "29ec9c63c152d59750f8903c3c0bc82e",
"semantic_hash": ""
},
@@ -5620,7 +5620,7 @@
"semantic_hash": ""
},
"assets/admin/components/appointments/ConfirmAppointmentModal.tsx": {
"mtime": 1784464897.1870914,
"mtime": 1784800330.8685021,
"ast_hash": "21b4c13aa4b240e8cde0225c9bbe93af",
"semantic_hash": ""
},
@@ -5655,12 +5655,12 @@
"semantic_hash": ""
},
"src/Appointment/Security/AppointmentAccessChecker.php": {
"mtime": 1784724354.5164225,
"mtime": 1784727191.2147117,
"ast_hash": "e89261caf08ea9112b1a952c1af68392",
"semantic_hash": ""
},
"src/Appointment/Service/AppointmentConfirmationService.php": {
"mtime": 1784464902.5814095,
"mtime": 1784800330.9388812,
"ast_hash": "7e4509fa018215d1553d90b4eec1beab",
"semantic_hash": ""
},
@@ -5685,7 +5685,7 @@
"semantic_hash": ""
},
"tests/Appointment/AppointmentConfirmFlowTest.php": {
"mtime": 1784464902.6853552,
"mtime": 1784800330.9432747,
"ast_hash": "52bc5d0a0a36058d3a8be6a26ffbf421",
"semantic_hash": ""
},
@@ -5725,7 +5725,7 @@
"semantic_hash": ""
},
"tests/Patient/SessionInsuranceShareTest.php": {
"mtime": 1784464902.7527723,
"mtime": 1784800330.9435008,
"ast_hash": "e1e4916bfbcaf3f309b4c7ad6557d954",
"semantic_hash": ""
},
@@ -5825,7 +5825,7 @@
"semantic_hash": ""
},
"assets/admin/components/appointments/ConfirmAppointmentModal.test.tsx": {
"mtime": 1784464897.1859367,
"mtime": 1784800330.8682916,
"ast_hash": "3e019b74d7358bd476bef3f1a8be4e47",
"semantic_hash": ""
},
@@ -5860,7 +5860,7 @@
"semantic_hash": ""
},
"assets/admin/pages/ClinicDetailPage.test.tsx": {
"mtime": 1784464897.2650912,
"mtime": 1784806088.596342,
"ast_hash": "0ffb389a98ed2cc05b7048f1083f2d58",
"semantic_hash": ""
},
@@ -5955,8 +5955,8 @@
"semantic_hash": ""
},
"src/Shared/EventSubscriber/AdminCspSubscriber.php": {
"mtime": 1784647364.4685004,
"ast_hash": "51968a10cbb2a67a3178c17e4f008d15",
"mtime": 1784806088.6016517,
"ast_hash": "2616bb5ec5d87d1c98b5564cc6a695f1",
"semantic_hash": ""
},
"src/Shared/EventSubscriber/MaintenanceSubscriber.php": {
@@ -6025,8 +6025,8 @@
"semantic_hash": ""
},
"tests/Shared/AdminCspSubscriberTest.php": {
"mtime": 1784647364.4691322,
"ast_hash": "57261fa69acc2a109bea95bad7145e67",
"mtime": 1784806088.6021926,
"ast_hash": "3ddd34bc065d307c664d3e5142b754e0",
"semantic_hash": ""
},
"tests/Shared/MaintenanceModeTest.php": {
@@ -6075,8 +6075,8 @@
"semantic_hash": ""
},
"docs/security/AUDIT-2026-07-19.md": {
"mtime": 1784482277.728783,
"ast_hash": "b091d42c009abfa567a6a6a0347309be",
"mtime": 1784806088.5996838,
"ast_hash": "408d4d454c9bba340a6b3cbdc2b52293",
"semantic_hash": ""
},
"src/Doctor/Command/PurgeUnclaimedDoctorsCommand.php": {
@@ -6085,7 +6085,7 @@
"semantic_hash": ""
},
"tests/Appointment/OnlineBookingManagementTest.php": {
"mtime": 1784726140.3336258,
"mtime": 1784727191.2227325,
"ast_hash": "11953bb678ab431f6d6c926f3ef7dbb9",
"semantic_hash": ""
},
@@ -6100,7 +6100,7 @@
"semantic_hash": ""
},
"tests/Insurance/TenantInsurancePerDoctorTest.php": {
"mtime": 1784648763.7617908,
"mtime": 1784727191.224061,
"ast_hash": "41898e07774ffb26e89402787af7a224",
"semantic_hash": ""
},
@@ -6110,13 +6110,18 @@
"semantic_hash": ""
},
".claude/prompt/fix-appointment-management-online-toggle.md": {
"mtime": 1784723760.132703,
"mtime": 1784727191.1322014,
"ast_hash": "f3f7214bb446e4344f821c0178aaacde",
"semantic_hash": ""
},
".claude/prompt/per-doctor-insurance-contracts.md": {
"mtime": 1784648155.824305,
"mtime": 1784727191.1325386,
"ast_hash": "064eb9e8ea671191a42ec6e11f49c40b",
"semantic_hash": ""
},
"seed_testdata.php": {
"mtime": 1784801102.5859623,
"ast_hash": "a04969acb8b76ebb4d3452cbf804f0a3",
"semantic_hash": ""
}
}
@@ -212,8 +212,8 @@ class MyAppointmentsController extends BaseController
}
/**
* Booking-scoped patient lookup by mobile. Lets the booking form search an
* existing patient before asking for national code / name. Unlike
* Booking-scoped patient lookup by mobile OR national code. Lets the booking
* form search an existing patient before asking for national code / name. Unlike
* /patient/search-user this is not gated by the patient_records feature and
* allows ROLE_ADMIN, because booking must work regardless of subscription.
*/
@@ -226,17 +226,28 @@ class MyAppointmentsController extends BaseController
return $this->error(ErrorCodes::FORBIDDEN, 'دسترسی ندارید', 403);
}
$mobile = InputValidator::toEnglishDigits(trim((string) $request->query->get('mobile', '')));
if (!InputValidator::isValidIranMobile($mobile)) {
return $this->error(ErrorCodes::VALIDATION, 'شماره موبایل نامعتبر است', 422, 'mobile');
// Lookup by mobile OR national code — the booking form lets the user
// search either way. National code takes precedence when both are sent.
$mobile = InputValidator::toEnglishDigits(trim((string) $request->query->get('mobile', '')));
$nationalQuery = InputValidator::toEnglishDigits(trim((string) $request->query->get('national_code', '')));
if ($nationalQuery !== '') {
if (!InputValidator::isValidIranNationalCode($nationalQuery)) {
return $this->error(ErrorCodes::VALIDATION, 'کد ملی نامعتبر است', 422, 'national_code');
}
// National code lives on the profile (profiles.national_code), not on User.
$profile = $this->profileRepo->findOneByNationalCode($nationalQuery);
$patient = $profile?->getUser();
} elseif (InputValidator::isValidIranMobile($mobile)) {
$patient = $this->userRepo->findByMobile($mobile);
} else {
return $this->error(ErrorCodes::VALIDATION, 'شماره موبایل یا کد ملی نامعتبر است', 422, 'mobile');
}
$patient = $this->userRepo->findByMobile($mobile);
if ($patient === null) {
return $this->success(['found' => false]);
}
// National code lives on the profile (profiles.national_code), not on User.
$nationalCode = $this->profileRepo->findByUser($patient)?->getNationalCode();
return $this->success([
+37 -2
View File
@@ -7,8 +7,8 @@ use App\Tests\ApiTestCase;
use App\UserProfile\Entity\UserProfile;
/**
* GET /api/v1/my/appointment/patient-lookup mobile-first patient search used
* by the booking form before asking for national code / name.
* GET /api/v1/my/appointment/patient-lookup patient search by mobile OR
* national code, used by the booking form before asking for national code / name.
*/
class PatientLookupTest extends ApiTestCase
{
@@ -75,6 +75,41 @@ class PatientLookupTest extends ApiTestCase
self::assertSame(422, $this->responseCode());
}
public function testFoundByNationalCode(): void
{
$mobile = $this->mobile();
$nc = $this->nationalCode();
$patient = $this->createUser(['ROLE_USER'], $mobile);
$patient->setRealName('کدملی جو');
$profile = new UserProfile($patient);
$profile->setNationalCode($nc);
$this->em->persist($profile);
$this->em->flush();
$res = $this->authJson('GET', '/api/v1/my/appointment/patient-lookup?national_code=' . $nc, $this->booker());
self::assertSame(200, $this->responseCode());
self::assertTrue($res['data']['found']);
self::assertSame('کدملی جو', $res['data']['name']);
self::assertSame($mobile, $res['data']['mobile']);
self::assertSame($nc, $res['data']['national_code']);
}
public function testNationalCodeNotFound(): void
{
$res = $this->authJson('GET', '/api/v1/my/appointment/patient-lookup?national_code=' . $this->nationalCode(), $this->booker());
self::assertSame(200, $this->responseCode());
self::assertFalse($res['data']['found']);
}
public function testInvalidNationalCodeIs422(): void
{
$this->authJson('GET', '/api/v1/my/appointment/patient-lookup?national_code=123', $this->booker());
self::assertSame(422, $this->responseCode());
}
public function testPlainUserIsForbidden(): void
{
$this->authJson('GET', '/api/v1/my/appointment/patient-lookup?mobile=' . $this->mobile(), $this->createUser(['ROLE_USER']));