Add AST JSON files for doctor service, tag controller, and SMS log entities

- Created new AST JSON file for the doctor service API documentation, detailing endpoints, parameters, and responses.
- Added AST JSON file for the TagController, including methods and their relationships with imported classes.
- Introduced AST JSON file for the SmsLog entity, outlining its methods and dependencies.
This commit is contained in:
hamed
2026-07-01 14:21:08 +03:30
parent 3120132274
commit a31e8b4314
43 changed files with 3528 additions and 1084 deletions
+140
View File
@@ -0,0 +1,140 @@
# ارسال پیامک خوش‌آمد هنگام تعریف منشی جدید
## پروژه
`clinicpro` (backend — Symfony)
## زمینه
هنگام تعریف منشی جدید از طریق `POST /api/v1/secretary`، یک User با نقش `ROLE_SECRETARY` ساخته (یا کاربر موجود بازاستفاده) می‌شود، اما **هیچ پیامکی به منشی ارسال نمی‌شود**. منشی هیچ اطلاعی از شماره‌کاربری، رمز و لینک ورود ندارد.
الگوی مشابه در پروژه از قبل وجود دارد: هنگام تأیید پیش‌ثبت‌نام (`PreRegistrationController` با تگ `TAG_PRE_REGISTRATION`) و دعوت پزشک به کلینیک (`ClinicInvitationService::sendSms` با تگ `TAG_CLINIC_INVITATION`). این تسک همان الگو را برای منشی پیاده می‌کند.
## هدف
بعد از ساخت موفق منشی جدید، یک پیامک خوش‌آمد به شماره منشی ارسال شود. **متن پیامک باید از سیستم template پیامک بیاید** (تگ اختصاصی + `SmsMessageTemplate::DEFAULTS` به‌عنوان fallback، قابل ویرایش از DB)، نه hard-code داخل کنترلر.
## فایل‌های مرتبط
| فایل | نقش |
|------|-----|
| `src/Secretary/Controller/SecretaryController.php` | endpoint ساخت منشی — محل تزریق ارسال پیامک |
| `src/Sms/Entity/SmsLog.php` | ثابت‌های تگ (`TAG_*`) — افزودن تگ جدید |
| `src/Sms/Entity/SmsMessageTemplate.php` | آرایه `DEFAULTS` — افزودن متن پیش‌فرض template |
| `src/Sms/Service/SmsService.php` | `dispatchAsync(...)` — ارسال async پیامک |
| `src/Sms/Service/SmsTextResolver.php` | `resolve(tag, vars)` — resolve متن template و جایگزینی `{key}` |
| `src/ClinicInvitation/Service/ClinicInvitationService.php` | **الگوی مرجع** ارسال پیامک با template |
| `docs/api/secretary.md` + `docs/api/sms.md` | مستندات — باید به‌روز شوند |
## وضعیت فعلی
در `SecretaryController::create()` بعد از ساخت user، فقط ذخیره می‌شود و هیچ پیامکی نمی‌رود:
```php
// Assign ROLE_SECRETARY
$roles = $secretaryUser->getRoles();
if (!in_array('ROLE_SECRETARY', $roles, true)) {
$roles[] = 'ROLE_SECRETARY';
$secretaryUser->setRoles(array_values(array_unique($roles)));
}
$this->userRepo->save($secretaryUser);
// ... check duplicate ...
$secretary = new DoctorSecretary($doctor, $secretaryUser, $ownerType, $ownerClinic);
// ...
$this->secretaryRepo->save($secretary);
return $this->success(['data' => $secretary->toArray()], 201);
```
الگوی مرجع ارسال پیامک با template (از `ClinicInvitationService`):
```php
$message = $this->smsText->resolve(\App\Sms\Entity\SmsLog::TAG_CLINIC_INVITATION, [
'clinic' => $clinicName,
'link' => $link,
]);
$this->smsService->dispatchAsync($inv->getMobile(), $message, tag: \App\Sms\Entity\SmsLog::TAG_CLINIC_INVITATION);
```
ساختار `DEFAULTS` در `SmsMessageTemplate` (هر تگ: `title`, `body` با placeholderهای `{key}`, `variables[]`):
```php
SmsLog::TAG_PRE_REGISTRATION => [
'title' => 'پیش‌ثبت‌نام',
'body' => 'به کلینیک پرو خوش آمدید! شماره‌کاربری: {username} | رمز عبور: {password} | لینک ورود: {link}',
'variables' => ['username', 'password', 'link'],
],
```
## وظایف
### ۱. افزودن تگ جدید در `SmsLog`
در `src/Sms/Entity/SmsLog.php` یک ثابت تگ جدید اضافه کن (هم‌سبک بقیه تگ‌ها):
```php
public const TAG_SECRETARY = 'secretary';
```
> نکته: investigator گزارش داد تگی به نام `TAG_WELCOME` هم موجود است — قبل از افزودن، فایل را بخوان؛ اگر تگ عمومی خوش‌آمد مناسب بود از همان استفاده کن، در غیر این صورت `TAG_SECRETARY` را اضافه کن. یک تگ اختصاصی «منشی» بهتر است چون متن template مستقل و قابل ویرایش می‌شود.
### ۲. افزودن template پیش‌فرض در `SmsMessageTemplate::DEFAULTS`
یک entry جدید برای تگ منشی اضافه کن. متن باید شامل نام کلینیک/دکتر و اطلاعات ورود باشد:
```php
SmsLog::TAG_SECRETARY => [
'title' => 'دعوت به‌عنوان منشی',
'body' => "شما به‌عنوان منشی {owner} در کلینیک‌پرو تعریف شدید.\nشماره‌کاربری: {username}\nلینک ورود: {link}",
'variables' => ['owner', 'username', 'link'],
],
```
- `{owner}` = نام دکتر یا نام کلینیک (بسته به `$ownerType`).
- `{username}` = شماره موبایل منشی (`$mobile`).
- `{link}` = لینک ورود پنل (از سرویس `$appUrl` مثل بقیه، rtrim + مسیر ورود).
- اگر رمز عبور در body لازم شد، فقط زمانی که کاربر **جدید** ساخته شده و `password` در ورودی آمده — رمز خام را نگه‌دار و در vars بگذار (متغیر محلی، نه از دیتابیس؛ hash قابل بازگشت نیست).
### ۳. تزریق سرویس‌های SMS در کنترلر
در constructor `SecretaryController` این‌ها را اضافه کن (هم‌سبک `ClinicInvitationService`):
```php
private readonly \App\Sms\Service\SmsService $smsService,
private readonly \App\Sms\Service\SmsTextResolver $smsText,
private readonly string $appUrl, // همان param که ClinicInvitationService می‌گیرد
```
> `$appUrl` را از همان جایی bind کن که `ClinicInvitationService` می‌گیرد — `config/services.yaml` را بررسی کن و همان `$appUrl` را برای `SecretaryController` هم bind کن (یا اگر global bind است، خودکار تزریق می‌شود).
### ۴. ارسال پیامک بعد از ساخت موفق منشی
در `create()`، **بعد از** `$this->secretaryRepo->save($secretary);` و **قبل از** `return`، پیامک را resolve و dispatch کن:
```php
$ownerName = $ownerClinic !== null
? ($ownerClinic->getName() ?? 'کلینیک')
: ($doctor->getUser()->getRealName() ?? 'پزشک');
$link = rtrim($this->appUrl, '/') . '/login';
$message = $this->smsText->resolve(\App\Sms\Entity\SmsLog::TAG_SECRETARY, [
'owner' => $ownerName,
'username' => $mobile,
'link' => $link,
]);
$this->smsService->dispatchAsync($mobile, $message, tag: \App\Sms\Entity\SmsLog::TAG_SECRETARY);
```
## نکات مهم
- **ارسال async است** — `dispatchAsync` فقط در صف Messenger می‌گذارد؛ ارسال واقعی توسط worker (`messenger:consume async`) انجام می‌شود. برای تست local باید worker در حال اجرا باشد.
- **متن hard-code نکن** — همیشه از `SmsTextResolver::resolve(tag, vars)` استفاده کن تا ادمین بتواند از DB متن را ویرایش کند. `DEFAULTS` فقط fallback است.
- **placeholderها دقیقاً `{key}`** باشند و کلیدهای `variables[]` با کلیدهای آرایه `vars` که به `resolve` می‌دهی یکی باشند.
- **duplicate/خطا** — اگر منشی تکراری بود (خط ۱۰۱–۱۰۳) یا هر خطای زودهنگام، `return` قبل از رسیدن به کد ارسال رخ می‌دهد؛ پس پیامک فقط روی مسیر موفق ساخت می‌رود. درست است — همین رفتار مطلوب است.
- **کاربر موجود بازاستفاده‌شده**: تصمیم بگیر آیا برای کاربری که از قبل وجود داشت (`findByMobile` غیر null) هم پیامک برود یا فقط برای کاربر تازه‌ساخته. پیشنهاد: چون این یک «دعوت به نقش منشی» است، برای هر دو حالت (چون رابطه منشی جدید ساخته می‌شود) پیامک منطقی است؛ ولی اگر رمز در body هست، رمز را فقط برای کاربر جدید بگذار.
- **مستندات (Standing Rule)**: چون `src/Secretary/*` و `src/Sms/*` تغییر می‌کنند، در همین session هم `docs/api/secretary.md` (ذکر ارسال پیامک هنگام create) و هم `docs/api/sms.md` (تگ جدید + template پیش‌فرض) را به‌روز کن.
- بعد از تغییر کد: `ddev exec php bin/console cache:clear`. اگر Entity تغییری در schema نداشت (فقط ثابت/آرایه `DEFAULTS`)، migration لازم نیست — ولی اگر template را seed می‌کنی، از همان مسیر seed موجود پروژه استفاده کن.
+4
View File
@@ -104,6 +104,10 @@ services:
arguments:
$appUrl: '%env(APP_BASE_URL)%'
App\Secretary\Controller\SecretaryController:
arguments:
$appUrl: '%env(APP_BASE_URL)%'
App\Sms\Controller\SmsWalletController:
arguments:
$appBaseUrl: '%env(APP_BASE_URL)%'
+2
View File
@@ -124,6 +124,8 @@ Create a secretary for a doctor.
| `doctor` | منشی توسط خود دکتر تعریف شده — فقط مطب شخصی |
| `clinic` | منشی توسط مدیر کلینیک تعریف شده — فقط کلینیک |
**پیامک خوش‌آمد:** پس از ساخت موفق منشی، یک پیامک به‌صورت async به `mobile_number` منشی ارسال می‌شود (تگ `secretary`). متن از قالب ویرایش‌پذیر DB می‌آید (fallback به پیش‌فرض) و placeholderهای `{owner}` (نام دکتر یا کلینیک بسته به `owner_type``{username}` (موبایل منشی) و `{link}` (لینک ورود) را جایگزین می‌کند. ویرایش متن از `PATCH /api/v1/admin/sms/messages/secretary` — رجوع به [sms.md](sms.md).
### Errors
| Code | HTTP | Description |
+3 -1
View File
@@ -482,9 +482,11 @@ Updated template with `status: "rejected"`.
متن پیامک‌های سیستمی (OTP، پرداخت، دعوت کلینیک، پیش‌ثبت‌نام، تأیید موبایل) از پنل قابل ویرایش است و بر اساس **تگ** کلیددار می‌شود. هر متن placeholderهای مجاز خود را دارد (مثل `{code}`، `{doctor}`، `{date}`). هنگام ارسال، `SmsTextResolver` متنِ ویرایش‌شده‌ی DB را می‌گیرد و placeholderها را جایگزین می‌کند؛ اگر رکوردی نبود به متن پیش‌فرض fallback می‌شود.
> تگ‌ها: `otp`، `payment`، `clinic_invitation`، `pre_registration`، `notification_mobile`، `welcome`. (پیامک قالبیِ کاربر با تگ `user_template` جداگانه از طریق `POST /api/v1/sms/template` مدیریت می‌شود.)
> تگ‌ها: `otp`، `payment`، `clinic_invitation`، `pre_registration`، `notification_mobile`، `welcome`، `secretary`. (پیامک قالبیِ کاربر با تگ `user_template` جداگانه از طریق `POST /api/v1/sms/template` مدیریت می‌شود.)
>
> تگ `welcome`: پیامک خوش‌آمد که هنگام افزودن پزشک/کلینیک توسط نماینده (`POST /api/v1/representation/doctor|clinic`) به‌صورت async به موبایل پزشک/مالک ارسال می‌شود. متن فعلاً ثابت است (نام + `site_name`)، نه از قالب DB.
>
> تگ `secretary`: پیامک خوش‌آمد که هنگام تعریف منشی جدید (`POST /api/v1/secretary`) به‌صورت async به موبایل منشی ارسال می‌شود. placeholderها: `{owner}` (نام دکتر یا کلینیک)، `{username}` (موبایل منشی)، `{link}` (لینک ورود). متن از قالب DB می‌آید (fallback به پیش‌فرض `SmsMessageTemplate::DEFAULTS`).
### GET `/api/v1/admin/sms/messages`
+19 -1
View File
@@ -654,10 +654,28 @@
"652": "Community 652",
"653": "Community 653",
"654": "Community 654",
"655": "Community 655",
"656": "Community 656",
"657": "Community 657",
"658": "Community 658",
"659": "Community 659",
"660": "Community 660",
"661": "Community 661",
"662": "Community 662",
"663": "Community 663",
"664": "Community 664",
"665": "Community 665",
"666": "Community 666",
"667": "Community 667",
"668": "Community 668",
"669": "Community 669",
"670": "Community 670",
"672": "Community 672"
"671": "Community 671",
"672": "Community 672",
"673": "Community 673",
"674": "Community 674",
"675": "Community 675",
"676": "Community 676",
"677": "Community 677",
"678": "Community 678"
}
+221 -127
View File
@@ -1,16 +1,16 @@
# Graph Report - clinicpro (2026-06-30)
# Graph Report - clinicpro (2026-07-01)
## Corpus Check
- 663 files · ~463,560 words
- 668 files · ~472,125 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 8328 nodes · 11514 edges · 661 communities (532 shown, 129 thin omitted)
- 8432 nodes · 11619 edges · 679 communities (551 shown, 128 thin omitted)
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 264 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `22937dfa`
- Built from commit: `31201322`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -656,11 +656,29 @@
- [[_COMMUNITY_Community 652|Community 652]]
- [[_COMMUNITY_Community 653|Community 653]]
- [[_COMMUNITY_Community 654|Community 654]]
- [[_COMMUNITY_Community 655|Community 655]]
- [[_COMMUNITY_Community 656|Community 656]]
- [[_COMMUNITY_Community 657|Community 657]]
- [[_COMMUNITY_Community 658|Community 658]]
- [[_COMMUNITY_Community 659|Community 659]]
- [[_COMMUNITY_Community 660|Community 660]]
- [[_COMMUNITY_Community 661|Community 661]]
- [[_COMMUNITY_Community 662|Community 662]]
- [[_COMMUNITY_Community 663|Community 663]]
- [[_COMMUNITY_Community 664|Community 664]]
- [[_COMMUNITY_Community 665|Community 665]]
- [[_COMMUNITY_Community 666|Community 666]]
- [[_COMMUNITY_Community 667|Community 667]]
- [[_COMMUNITY_Community 668|Community 668]]
- [[_COMMUNITY_Community 669|Community 669]]
- [[_COMMUNITY_Community 671|Community 671]]
- [[_COMMUNITY_Community 672|Community 672]]
- [[_COMMUNITY_Community 673|Community 673]]
- [[_COMMUNITY_Community 674|Community 674]]
- [[_COMMUNITY_Community 675|Community 675]]
- [[_COMMUNITY_Community 676|Community 676]]
- [[_COMMUNITY_Community 677|Community 677]]
- [[_COMMUNITY_Community 678|Community 678]]
## God Nodes (most connected - your core abstractions)
1. `BaseController` - 76 edges
@@ -679,37 +697,37 @@
assets/admin/components/ServiceTariffModal.tsx → assets/admin/lib/utils.ts
- `PersianDatePicker()` --calls--> `formatDate()` [EXTRACTED]
assets/admin/components/ui/PersianDatePicker.tsx → assets/admin/lib/utils.ts
- `MyFinancialPage()` --calls--> `formatRial()` [EXTRACTED]
assets/admin/pages/MyFinancialPage.tsx → assets/admin/lib/utils.ts
- `RepresentationSettlementPage()` --calls--> `formatRial()` [EXTRACTED]
assets/admin/pages/RepresentationSettlementPage.tsx → assets/admin/lib/utils.ts
- `LogsPage()` --calls--> `formatDateTime()` [EXTRACTED]
assets/admin/pages/LogsPage.tsx → assets/admin/lib/utils.ts
- `SmsPage()` --calls--> `formatDateTime()` [EXTRACTED]
assets/admin/pages/SmsPage.tsx → assets/admin/lib/utils.ts
- `NewAppointmentModal()` --calls--> `useAuthStore` [EXTRACTED]
assets/admin/pages/AppointmentsPage.tsx → assets/admin/stores/authStore.ts
## Import Cycles
- None detected.
## Communities (661 total, 129 thin omitted)
## Communities (679 total, 128 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.05
Nodes (43): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, AddForm, addSchema (+35 more)
Nodes (40): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, LogoUploadField(), TabActions() (+32 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (41): AddressData, AddrForm, addrSchema, AVATAR_COLORS, BookingMeta, CityOpt, DateOverrideData, DEFAULT_BOOKING_META (+33 more)
### Community 2 - "Community 2"
Cohesion: 0.07
Nodes (27): get, BeforeInstallPromptEvent, usePwaInstall(), api, ApiError, getToken(), refreshOnce(), request() (+19 more)
Cohesion: 0.06
Nodes (26): get, api, ApiError, getToken(), refreshOnce(), request(), { refreshMock, logoutMock }, replaceMock (+18 more)
### Community 3 - "Community 3"
Cohesion: 0.04
Nodes (71): PaginatedResponse, formatDate(), ALL_STATUSES, AppointmentDetailPage(), STATUS_FILTERS, FILTERS, Breakdown, SOURCE_LABEL (+63 more)
Cohesion: 0.05
Nodes (50): ApiResponse, PaginatedResponse, formatDate(), ALL_STATUSES, AppointmentDetailPage(), STATUS_FILTERS, FILTERS, Breakdown (+42 more)
### Community 4 - "Community 4"
Cohesion: 0.06
Nodes (8): DoctorService, Doctor, DoctorServiceRepository, Collection, self, User, WeeklySchedule, ManagerRegistry
Cohesion: 0.05
Nodes (11): DoctorServiceController, DoctorService, Doctor, DoctorServiceRepository, Collection, self, User, WeeklySchedule (+3 more)
### Community 5 - "Community 5"
Cohesion: 0.07
@@ -725,7 +743,7 @@ Nodes (5): Clinic, Collection, Doctor, self, User
### Community 8 - "Community 8"
Cohesion: 0.08
Nodes (28): useSubscription(), AdminLayout(), avatarBg(), buildSections(), HUES, Props, ROLE_LABELS, Section (+20 more)
Nodes (27): useSubscription(), AdminLayout(), avatarBg(), buildSections(), HUES, Props, ROLE_LABELS, Section (+19 more)
### Community 9 - "Community 9"
Cohesion: 0.04
@@ -736,28 +754,28 @@ Cohesion: 0.04
Nodes (46): Clinic Address Management, Clinic API, DELETE `/api/v1/admin/clinic/{clinicUuid}/doctor/{doctorUuid}`, `DELETE /api/v1/clinic/{clinicUuid}/address/{addressUuid}`, Errors, Errors, Errors, Errors (+38 more)
### Community 11 - "Community 11"
Cohesion: 0.05
Nodes (33): usePaymentConfig(), ApiResponse, emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema, PLAN_DISPLAY (+25 more)
Cohesion: 0.06
Nodes (38): PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), SmsPage(), STATUS_LOG_META, Tab, TAG_FILTER_OPTIONS, TAG_LABELS (+30 more)
### Community 12 - "Community 12"
Cohesion: 0.05
Nodes (44): Clinic Doctor Invitation API, DELETE `/api/v1/admin/clinic/invitation/{invUuid}`, Errors, Errors, Errors, Errors, Errors, Errors (+36 more)
### Community 13 - "Community 13"
Cohesion: 0.08
Nodes (28): cn(), formatDateTime(), iranMobileOptionalSchema, iranMobileSchema, isValidIranMobile(), maskMobile(), sanitizeMobileInput(), toDate() (+20 more)
Cohesion: 0.07
Nodes (37): FreeVisitPrice(), Pricing, cn(), formatDateTime(), formatRial(), iranMobileOptionalSchema, iranMobileSchema, isValidIranMobile() (+29 more)
### Community 14 - "Community 14"
Cohesion: 0.15
Nodes (8): AppointmentSettingsController, Holiday, HolidayRepository, JsonResponse, Request, User, Doctor, ManagerRegistry
### Community 15 - "Community 15"
Cohesion: 0.10
Nodes (13): PaymentController, MockGateway, SepGateway, JsonResponse, Payment, PaymentGatewayInterface, Request, Response (+5 more)
Cohesion: 0.09
Nodes (13): PaymentController, MellatGateway, MockGateway, JsonResponse, Payment, PaymentGatewayInterface, Request, Response (+5 more)
### Community 16 - "Community 16"
Cohesion: 0.07
Nodes (7): PatientSession, SmsWallet, Appointment, Collection, PatientRecord, self, SessionService
Cohesion: 0.06
Nodes (8): PatientSession, SmsWallet, AppointmentExpiryService, Appointment, Collection, PatientRecord, self, SessionService
### Community 17 - "Community 17"
Cohesion: 0.05
@@ -768,20 +786,20 @@ Cohesion: 0.05
Nodes (38): API, API, API, API, API, Route, Route, Route (+30 more)
### Community 19 - "Community 19"
Cohesion: 0.09
Nodes (17): Contract, InsuranceOption, KIND_LABEL, FormData, schema, AdminUser, ChangeRoleModal(), getPrimaryRole() (+9 more)
Cohesion: 0.20
Nodes (8): AdminUser, ChangeRoleModal(), getPrimaryRole(), HUES_LIST, ROLE_META, ROLE_TABS, RoleBadge(), UserStats
### Community 20 - "Community 20"
Cohesion: 0.12
Nodes (4): AdminApiController, InputValidator, JsonResponse, Request
Cohesion: 0.15
Nodes (3): AdminApiController, JsonResponse, Request
### Community 21 - "Community 21"
Cohesion: 0.05
Nodes (42): FreeVisitPrice(), Pricing, formatNumber(), formatRial(), ClinicDetailPage(), AdminCharts, AdminDashboard(), AdminRecent (+34 more)
Nodes (37): formatNumber(), ClinicDetailPage(), AdminCharts, AdminDashboard(), AdminRecent, AdminStats, APPT_CLS, APPT_COLOR (+29 more)
### Community 22 - "Community 22"
Cohesion: 0.11
Nodes (14): RatingController, Like, Rate, LikeRepository, RateRepository, JsonResponse, Request, User (+6 more)
Cohesion: 0.09
Nodes (15): RatingController, Like, Rate, CommentListNPlusOneTest, LikeRepository, RateRepository, JsonResponse, Request (+7 more)
### Community 23 - "Community 23"
Cohesion: 0.05
@@ -796,8 +814,8 @@ Cohesion: 0.05
Nodes (39): Appointment API, Error Responses, Errors, Errors, Errors, Errors, Errors, Errors (+31 more)
### Community 26 - "Community 26"
Cohesion: 0.15
Nodes (7): InsuranceController, EntityInsurancePricing, EntityInsurancePricingRepository, JsonResponse, Request, User, ManagerRegistry
Cohesion: 0.24
Nodes (4): InsuranceController, JsonResponse, Request, User
### Community 27 - "Community 27"
Cohesion: 0.05
@@ -808,8 +826,8 @@ Cohesion: 0.09
Nodes (4): Appointment, Doctor, self, User
### Community 29 - "Community 29"
Cohesion: 0.06
Nodes (34): Bulk import / export, DELETE `/api/v1/admin/city/{id}`, DELETE `/api/v1/admin/province/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/cities` (+26 more)
Cohesion: 0.10
Nodes (21): Bulk import / export, DELETE `/api/v1/admin/city/{id}`, DELETE `/api/v1/admin/province/{id}`, Errors, Errors, GET `/api/v1/admin/provinces`, GET `/api/v1/categorys/{bundle}` *(Legacy)*, GET `/api/v1/provinces` (+13 more)
### Community 30 - "Community 30"
Cohesion: 0.08
@@ -824,8 +842,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.08
Nodes (20): CoverageRow, Draft, KIND, TenantInsurance, ServiceTariffModal(), TariffResponse, TariffRow, EMPTY_ITEMS (+12 more)
Cohesion: 0.04
Nodes (40): CoverageRow, Draft, KIND, TenantInsurance, ServiceTariffModal(), TariffResponse, TariffRow, Contract (+32 more)
### Community 34 - "Community 34"
Cohesion: 0.06
@@ -857,7 +875,7 @@ Nodes (4): User, PasswordAuthenticatedUserInterface, self, UserInterface
### Community 41 - "Community 41"
Cohesion: 0.06
Nodes (23): CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, LogoUploadField(), ProvinceForm, provinceSchema (+15 more)
Nodes (21): CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, ProvinceForm, provinceSchema, ServiceForm (+13 more)
### Community 42 - "Community 42"
Cohesion: 0.07
@@ -888,8 +906,8 @@ Cohesion: 0.11
Nodes (4): Payment, Appointment, self, User
### Community 49 - "Community 49"
Cohesion: 0.07
Nodes (21): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+13 more)
Cohesion: 0.09
Nodes (18): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+10 more)
### Community 50 - "Community 50"
Cohesion: 0.07
@@ -941,15 +959,15 @@ Nodes (22): Billing API — صورتحساب (فاز ۴ سیستم صورتحس
### Community 62 - "Community 62"
Cohesion: 0.08
Nodes (24): Bulk import / export, DELETE `/api/v1/admin/specialty/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/specialties`, GET `/api/v1/specialties` (+16 more)
Nodes (25): Bulk import / export, DELETE `/api/v1/admin/specialty/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/specialties`, GET `/api/v1/specialties` (+17 more)
### Community 63 - "Community 63"
Cohesion: 0.22
Nodes (5): AuthController, RateLimiterFactory, JsonResponse, Request, User
### Community 64 - "Community 64"
Cohesion: 0.20
Nodes (7): SmsWalletController, SmsSettingsRepository, SmsSettings, JsonResponse, Request, User, ManagerRegistry
Cohesion: 0.32
Nodes (4): SmsWalletController, JsonResponse, Request, User
### Community 65 - "Community 65"
Cohesion: 0.08
@@ -992,8 +1010,8 @@ Cohesion: 0.16
Nodes (5): DoctorSecretary, Clinic, Doctor, self, User
### Community 77 - "Community 77"
Cohesion: 0.10
Nodes (13): Claim, ClaimItem, DebtRow, InsuranceOption, KIND_LABEL, STATUS_FILTERS, STATUS_META, IbanItem (+5 more)
Cohesion: 0.08
Nodes (15): Claim, ClaimItem, DebtRow, InsuranceOption, KIND_LABEL, STATUS_FILTERS, STATUS_META, IbanItem (+7 more)
### Community 78 - "Community 78"
Cohesion: 0.12
@@ -1021,7 +1039,7 @@ Nodes (29): devDependencies, @babel/core, @babel/preset-env, @babel/preset-react
### Community 86 - "Community 86"
Cohesion: 0.06
Nodes (15): AppointmentExpiryServiceTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, ServiceItemDeleteCleanupTest, ServiceItemStaffOwnershipTest, EntityManagerInterface, KernelBrowser (+7 more)
Nodes (15): AppointmentExpiryServiceTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, ServiceItemStaffOwnershipTest, EntityManagerInterface, KernelBrowser, CommentPaginationTest (+7 more)
### Community 87 - "Community 87"
Cohesion: 0.10
@@ -1044,8 +1062,8 @@ Cohesion: 0.10
Nodes (20): DELETE `/api/v1/admin/users/{uuid}`, Errors, Errors, GET `/api/v1/admin/users`, GET `/api/v1/admin/users/stats`, GET `/api/v1/admin/users/{uuid}`, POST `/api/v1/admin/users/{uuid}/status`, PUT `/api/v1/admin/users/{uuid}` (+12 more)
### Community 92 - "Community 92"
Cohesion: 0.10
Nodes (20): Bulk import / export, DELETE `/api/v1/admin/doctor-service/{id}`, Doctor Service API, Errors, Errors, Errors, Errors, GET `/api/v1/admin/doctor-services` (+12 more)
Cohesion: 0.09
Nodes (21): Bulk import / export, DELETE `/api/v1/admin/doctor-service/{id}`, Doctor Service API, Errors, Errors, Errors, Errors, GET `/api/v1/admin/doctor-services` (+13 more)
### Community 93 - "Community 93"
Cohesion: 0.10
@@ -1084,8 +1102,8 @@ Cohesion: 0.10
Nodes (19): Backend — endpoint اشتراک, Frontend — App.tsx, Frontend — authStore, Frontend — Sidebar, اعمال محدودیت‌های اشتراک در پنل ادمین (Frontend Gate), ترتیب اجرا, زمینه, فایل‌های مرتبط (+11 more)
### Community 102 - "Community 102"
Cohesion: 0.11
Nodes (19): Bulk import / export, DELETE `/api/v1/admin/tag/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/tags`, GET `/api/v1/tags` (+11 more)
Cohesion: 0.10
Nodes (20): Bulk import / export, DELETE `/api/v1/admin/tag/{id}`, Errors, Errors, Errors, Errors, GET `/api/v1/admin/tags`, GET `/api/v1/tags` (+12 more)
### Community 103 - "Community 103"
Cohesion: 0.35
@@ -1108,8 +1126,8 @@ Cohesion: 0.32
Nodes (6): AppointmentController, Appointment, Doctor, JsonResponse, Request, User
### Community 108 - "Community 108"
Cohesion: 0.18
Nodes (7): BaseController, CategoryController, CategoryImportController, JsonResponse, JsonResponse, Request, JsonResponse
Cohesion: 0.13
Nodes (10): BaseController, CategoryController, CategoryImportController, SmsMessageController, JsonResponse, JsonResponse, Request, JsonResponse (+2 more)
### Community 109 - "Community 109"
Cohesion: 0.29
@@ -1316,8 +1334,8 @@ Cohesion: 0.13
Nodes (13): Architecture, Auth, Backend (PHP/Symfony), Backend — `src/`, Category / Bundle system, Commands, Database, First-time setup (+5 more)
### Community 163 - "Community 163"
Cohesion: 0.13
Nodes (14): autoload, autoload-dev, psr-4, psr-4, conflict, symfony/symfony, description, license (+6 more)
Cohesion: 0.11
Nodes (18): autoload, autoload-dev, psr-4, psr-4, conflict, symfony/symfony, description, extra (+10 more)
### Community 164 - "Community 164"
Cohesion: 0.29
@@ -1364,7 +1382,7 @@ Cohesion: 0.35
Nodes (5): RepresentationController, JsonResponse, Representation, Request, User
### Community 176 - "Community 176"
Cohesion: 0.36
Cohesion: 0.33
Nodes (5): SecretaryController, DoctorSecretary, JsonResponse, Request, User
### Community 177 - "Community 177"
@@ -1457,7 +1475,7 @@ Nodes (13): Endpoint ها, PATCH /api/v1/secretary/{uuid}, POST /api/v1/secretar
### Community 201 - "Community 201"
Cohesion: 0.15
Nodes (13): Admin API, Clinic Invitation Management, GET `/api/v1/admin/payments`, GET `/api/v1/admin/representations`, GET /api/v1/admin/settings, PATCH /api/v1/admin/settings, Payment Management, Query Parameters (+5 more)
Nodes (13): Admin API, Clinic Invitation Management, GET `/api/v1/admin/representations`, GET `/api/v1/admin/secretaries`, GET /api/v1/admin/settings, PATCH /api/v1/admin/settings, Query Parameters, Query Parameters (+5 more)
### Community 202 - "Community 202"
Cohesion: 0.15
@@ -1480,16 +1498,16 @@ Cohesion: 0.35
Nodes (6): DashboardController, Clinic, DoctorSecretary, JsonResponse, Request, User
### Community 207 - "Community 207"
Cohesion: 0.07
Nodes (30): ۲. مدل داده و موجودیت‌ها, ۲.۱ کاربر (User), ۲.۱۰ پرداخت (Payment Types), ۲.۱۰.۱ پرداخت نوبت, ۲.۱۰.۲ پرداخت اشتراک, ۲.۱۱ پروفایل بیمار (Profile), ۲.۱۲ وبلاگ (Blog), ۲.۱۳ نظرات، لایک و امتیازدهی (+22 more)
Cohesion: 0.15
Nodes (13): ۲. مدل داده و موجودیت‌ها, ۲.۱ کاربر (User), ۲.۱۰ پرداخت (Payment Types), ۲.۱۰.۱ پرداخت نوبت, ۲.۱۰.۲ پرداخت اشتراک, ۲.۱۱ پروفایل بیمار (Profile), ۲.۱۲ وبلاگ (Blog), ۲.۳ دکتر (Doctor) (+5 more)
### Community 208 - "Community 208"
Cohesion: 0.23
Nodes (4): Like, Comment, self, User
### Community 213 - "Community 213"
Cohesion: 0.27
Nodes (3): MellatGateway, PaymentInitResult, PaymentVerifyResult
Cohesion: 0.08
Nodes (23): زمینه, ساده‌سازی «تنظیمات پیامک (SMS)» — فقط API Key از env, فایل‌های مرتبط, نکات مهم, هدف, وضعیت فعلی (کد واقعی), وظایف, پروژه (+15 more)
### Community 214 - "Community 214"
Cohesion: 0.15
@@ -1548,8 +1566,8 @@ Cohesion: 0.30
Nodes (6): AbstractAuthenticator, Passport, PasswordAuthenticator, Request, Response, TokenInterface
### Community 228 - "Community 228"
Cohesion: 0.17
Nodes (12): Bulk import / export, DELETE `/api/v1/admin/insurance/{id}`, DELETE `/api/v1/insurance/{id}`, EntityInsurancePricing — قیمت‌گذاری ویزیت بر اساس بیمه, GET `/api/v1/insurance/{id}`, GET `/api/v1/insurance-pricing`, Insurance API, Response `200` (+4 more)
Cohesion: 0.05
Nodes (43): Bulk import / export, DELETE `/api/v1/admin/insurance/{id}`, DELETE `/api/v1/billing/tenant-insurances/{uuid}`, DELETE `/api/v1/insurance/{id}`, EntityInsurancePricing — قیمت‌گذاری ویزیت بر اساس بیمه, Errors, Errors, Errors (+35 more)
### Community 229 - "Community 229"
Cohesion: 0.15
@@ -1648,8 +1666,8 @@ Cohesion: 0.18
Nodes (11): 1. 🔵 `POST` refresh token, 1. احراز هویت (Authentication), 2. 🟢 `GET` X-CSRF-Token, 3. 🟢 `GET` user info 🆕, Request Body, بخش دوم — مستند کامل API, خطاهای عمومی, فهرست مطالب (+3 more)
### Community 255 - "Community 255"
Cohesion: 0.11
Nodes (19): GET /api/v1/appointment-settings/slots — دریافت اسلات‌های خالی, GET /api/v1/categories/cities — شهرها, GET /api/v1/categories/states — استان‌ها, GET /api/v1/doctors/{id}, GET /api/v1/doctors/{id}/insurances, GET /api/v1/representations/{id}, GET /oauth/userinfo — اطلاعات کاربر (سازگار با دروپال), POST /api/v1/appointment-settings/holidays — ثبت تعطیلی (فقط ادمین) (+11 more)
Cohesion: 0.18
Nodes (11): GET /api/v1/doctors/{id}, GET /api/v1/doctors/{id}/insurances, GET /api/v1/representations/{id}, GET /oauth/userinfo — اطلاعات کاربر (سازگار با دروپال), POST /api/v1/representations/{id}/bank-accounts, POST /oauth/token — تجدید توکن (Refresh), POST /oauth/token — ورود به سیستم, Task-02: احراز هویت (Authentication) (+3 more)
### Community 256 - "Community 256"
Cohesion: 0.29
@@ -1684,8 +1702,8 @@ Cohesion: 0.33
Nodes (4): RepresentationRepository, ManagerRegistry, Representation, User
### Community 265 - "Community 265"
Cohesion: 0.08
Nodes (27): calcFinalPrice(), EMPTY_RECORDS, EMPTY_SESSIONS, fileNumber(), getPatientName(), getPatientPhone(), InsurancePricing, MyPatientsPageInner() (+19 more)
Cohesion: 0.15
Nodes (17): calcFinalPrice(), EMPTY_RECORDS, EMPTY_SESSIONS, fileNumber(), getPatientName(), getPatientPhone(), InsurancePricing, MyPatientsPageInner() (+9 more)
### Community 266 - "Community 266"
Cohesion: 0.33
@@ -1720,7 +1738,7 @@ Cohesion: 0.18
Nodes (10): Endpoint های موجود که تغییر می‌کنند, GET /api/v1/admin/dashboard/charts?from=UNIX&to=UNIX, GET /api/v1/dashboard/clinic, GET /api/v1/dashboard/doctor, تسک ۱۶: داشبورد هوشمند — چارت + فیلتر زمانی, توضیح, زمان تخمینی, فیلتر بازه زمانی (+2 more)
### Community 274 - "Community 274"
Cohesion: 0.19
Cohesion: 0.21
Nodes (5): Authentication, ClinicPro — API Documentation Index, Error Code Reference, Modules, Standard Response Envelope
### Community 275 - "Community 275"
@@ -1732,8 +1750,8 @@ Cohesion: 0.20
Nodes (9): Architecture Audit — ClinicPro Symfony 7 Migration, Architecture Score (بعد از اصلاحات), Architecture Violations, Executive Summary, Final Verdict (بعد از اصلاحات), Missing Requirements (کامل), اصلاحات اعمال‌شده (بعد از Audit), دلیل تصمیم (+1 more)
### Community 277 - "Community 277"
Cohesion: 0.08
Nodes (23): GET /api/v1/sms/balance — موجودی حساب پیامک, POST /api/v1/sms/queue — افزودن به صف, بخش اول — مستند محصول (PRD), ثبت‌نام دکتر — از طریق نماینده, ثبت‌نام دکتر — از طریق کلینیک, ثبت‌نام دکتر — مستقل, فهرست کلی, کلینیک پرو — مستند جامع فنی و API (+15 more)
Cohesion: 0.20
Nodes (9): بخش اول — مستند محصول (PRD), فهرست کلی, کلینیک پرو — مستند جامع فنی و API, ۵. فهرست مشکلات شناسایی‌شده و اصلاحات لازم, ۶. پیوست, ۶.۱ دیاگرام وضعیت نوبت, ۶.۲ جریان کمیسیون, ۶.۳ بررسی محدودیت منشی (+1 more)
### Community 279 - "Community 279"
Cohesion: 0.20
@@ -1836,8 +1854,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.04
Nodes (52): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 31. 🟡 `PATCH` patch, 32. 🔵 `POST` post, 33. 🔵 `POST` image_clinic, 34. 🔵 `POST` image logo, 36. 🟢 `GET` get my rate, 37. 🔵 `POST` post (+44 more)
Cohesion: 0.22
Nodes (9): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 33. 🔵 `POST` image_clinic, 6. کلینیک (Clinic), هدرهای اضافی, پارامترهای Query, پاسخ‌ها, پاسخ‌ها (+1 more)
### Community 306 - "Community 306"
Cohesion: 0.07
@@ -1984,8 +2002,8 @@ Cohesion: 0.26
Nodes (3): TenantInsuranceService, CoverageRule, TenantInsurance
### Community 347 - "Community 347"
Cohesion: 0.36
Nodes (3): DoctorServiceController, JsonResponse, Request
Cohesion: 0.11
Nodes (18): زمینه, فاز ۰ — Baseline, فاز ۱ — قرارداد پاسخ و Envelope, فاز ۲ — احراز هویت و مجوزها (Auth / RBAC), فاز ۳ — اعتبارسنجی ورودی و مدیریت خطا, فاز ۴ — امنیت API, فاز ۵ — پنل ادمین React SPA, فاز ۶ — یکپارچگی و سناریوهای واقعی کاربر (E2E) (+10 more)
### Community 348 - "Community 348"
Cohesion: 0.39
@@ -2152,8 +2170,8 @@ Cohesion: 0.33
Nodes (6): GET `/api/v1/admin/sms/logs`, GET `/api/v1/admin/sms/templates`, Query Parameters, Response `200`, Response `200`, SMS Management (Admin)
### Community 392 - "Community 392"
Cohesion: 0.33
Nodes (6): GET `/api/v1/admin/sms/templates`, GET /api/v1/sms/settings, PATCH /api/v1/sms/settings, Response `200`, SMS API, SMS Settings
Cohesion: 0.67
Nodes (3): GET /api/v1/sms/settings, PATCH /api/v1/sms/settings, SMS Settings
### Community 393 - "Community 393"
Cohesion: 0.33
@@ -2172,12 +2190,12 @@ Cohesion: 0.21
Nodes (6): ClaimAmountBoundsTest, ClaimsListNPlusOneTest, ClaimItem, Claim, Doctor, User
### Community 398 - "Community 398"
Cohesion: 0.33
Cohesion: 0.29
Nodes (4): initiate(), verify(), PaymentInitResult, PaymentVerifyResult
### Community 400 - "Community 400"
### Community 399 - "Community 399"
Cohesion: 0.23
Nodes (5): AbstractMigration, Schema, Version20260609131553, Schema, Version20260609134741
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260619121047
### Community 405 - "Community 405"
Cohesion: 0.47
@@ -2192,12 +2210,12 @@ Cohesion: 0.17
Nodes (11): دیپلوی ClinicPro روی Coolify (Docker Compose), رفع اشکال, مراحل دیپلوی, معماری دیپلوی, نکات عملیاتی, چند دامنه فرانت‌اند (مهم), ۱. ساخت Resource در Coolify, ۲. اختصاص دامنه (+3 more)
### Community 440 - "Community 440"
Cohesion: 0.43
Nodes (3): SmsMessageController, JsonResponse, Request
Cohesion: 0.11
Nodes (18): [F10] راهنمای کهنه در `CLAUDE.md`: endpoint `categorys/{bundle}` منتقل شده, [F11] داشبورد دکتر `GET /api/v1/dashboard/doctor` همیشه 500 (فیلد ناموجود در DQL) — ✅ رفع شد, [F1] phpstan: مقایسهٔ همیشه‌درست در محاسبهٔ estimated SMS — ✅ رفع شد, [F2] تست‌های PHPUnit به API خارجی Kavenegar درخواست واقعی می‌زنند, [F3] دیتابیس تست seed نشده — فقط کاربر ادمین وجود دارد, [F4] اسکریپت seeder `create_test_users.php` وجود ندارد, [F5] ادمین با JWT معتبر به `/api/doc` (Swagger UI) دسترسی ندارد (401), [F6] ناسازگاری کدهای خطا بین دامنه‌ها (+10 more)
### Community 452 - "Community 452"
Cohesion: 0.10
Nodes (12): ClinicAddress, ClinicDoctorItem, ClinicInvitation, EditForm, editSchema, HUES_LIST, INV_STATUS_MAP, IRAN_CENTER (+4 more)
Cohesion: 0.08
Nodes (16): ClinicAddress, ClinicDoctorItem, ClinicInvitation, EditForm, editSchema, HUES_LIST, INV_STATUS_MAP, IRAN_CENTER (+8 more)
### Community 456 - "Community 456"
Cohesion: 0.29
@@ -2208,8 +2226,8 @@ Cohesion: 0.47
Nodes (6): formatPersianDate(), gToJ(), jFirstDayOfWeek(), PersianDateInput(), todayGregorian(), toPersianNums()
### Community 459 - "Community 459"
Cohesion: 0.33
Nodes (6): API موجود (نیاز به تغییر ندارند), اپیک‌ها, اپیک ۳ — منشی (Secretary) — تکمیل, تغییرات مورد نیاز, توضیح, نیازمندی‌های کارکردی
Cohesion: 0.40
Nodes (5): API موجود (نیاز به تغییر ندارند), اپیک ۳ — منشی (Secretary) — تکمیل, تغییرات مورد نیاز, توضیح, نیازمندی‌های کارکردی
### Community 460 - "Community 460"
Cohesion: 0.33
@@ -2311,6 +2329,10 @@ Nodes (5): Errors, GET `/api/v1/representation/dashboard/summary`, GET `/api/v1/
Cohesion: 0.40
Nodes (5): Admin Endpoints, GET /api/v1/admin/sms/settings/review, GET /api/v1/admin/sms/wallet-report, POST /api/v1/admin/sms/settings/{id}/approve, POST /api/v1/admin/sms/settings/{id}/reject
### Community 491 - "Community 491"
Cohesion: 0.15
Nodes (5): EntityInsurancePricing, TenantInsuranceCleanupTest, EntityInsurancePricingRepository, TenantInsuranceCleanupService, ManagerRegistry
### Community 493 - "Community 493"
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)
@@ -2319,6 +2341,10 @@ Nodes (9): Backend Audit Backlog — ClinicPro, ☐ CRITICAL, ✅ DONE (committe
Cohesion: 0.50
Nodes (4): Error Codes, POST `/api/v1/user/reset-password`, Request Body, Response `200`
### Community 495 - "Community 495"
Cohesion: 0.12
Nodes (15): CORS — `config/packages/nelmio_cors.yaml`, MellatGateway — تشخیص فعال‌بودن, payment/config — `PaymentController::config()` (خط ۵۴۶), resolveGateway + callback (کد واقعی), رفع باگ‌های پروداکشن: CORS + payment/config 500 + درگاه‌های فعال و callback ملت, زمینه, فایل‌های مرتبط, فرانت — `SubscriptionPage.tsx` (+7 more)
### Community 496 - "Community 496"
Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/user/send-code`, Request Body, Response `200`
@@ -2336,8 +2362,8 @@ Cohesion: 0.40
Nodes (5): addMinutes(), calcSlotCount(), hasOverlap(), parseMinutes(), SessionEditor()
### Community 500 - "Community 500"
Cohesion: 0.40
Nodes (5): API موجود (نیاز به endpoint جدید ندارد), اپیک ۷ — داشبورد هوشمند (Smart Dashboard), تغییر مورد نیاز, توضیح, نیازمندی‌های کارکردی
Cohesion: 0.33
Nodes (6): API موجود (نیاز به endpoint جدید ندارد), اپیک‌ها, اپیک ۷ — داشبورد هوشمند (Smart Dashboard), تغییر مورد نیاز, توضیح, نیازمندی‌های کارکردی
### Community 501 - "Community 501"
Cohesion: 0.40
@@ -2480,16 +2506,16 @@ Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/admin/insurance`, Request Body (`application/json`), Response `201`
### Community 542 - "Community 542"
Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/insurance/`, Request Body (`application/json`), Response `201`
Cohesion: 0.15
Nodes (11): emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema, PLAN_DISPLAY, PlanForm, planSchema (+3 more)
### Community 543 - "Community 543"
Cohesion: 0.50
Nodes (4): Errors, PATCH `/api/v1/insurance/{id}`, Request Body, Response `200`
### Community 544 - "Community 544"
Cohesion: 0.50
Nodes (4): PUT `/api/v1/insurance-pricing`, Request Body, Response `200`, خطاها
Cohesion: 0.15
Nodes (12): ارسال پیامک خوش‌آمد هنگام تعریف منشی جدید, زمینه, فایل‌های مرتبط, نکات مهم, هدف, وضعیت فعلی, وظایف, پروژه (+4 more)
### Community 545 - "Community 545"
Cohesion: 0.50
@@ -2636,12 +2662,12 @@ Cohesion: 0.40
Nodes (5): Errors, PATCH `/api/v1/clinic-pro/doctor-address/{id}`, Path Parameters, Request Body, Response `200`
### Community 597 - "Community 597"
Cohesion: 0.67
Nodes (3): DELETE `/api/v1/sms/template/{uuid}`, Errors, Response `200`
Cohesion: 0.20
Nodes (10): Configuration, DELETE `/api/v1/sms/template/{uuid}`, Errors, Errors, GET `/api/v1/admin/sms/templates`, GET `/api/v1/sms/template/{uuid}`, Response `200`, Response `200` (+2 more)
### Community 598 - "Community 598"
Cohesion: 0.67
Nodes (3): Errors, GET `/api/v1/sms/template/{uuid}`, Response `200`
Cohesion: 0.31
Nodes (3): SepGateway, PaymentInitResult, PaymentVerifyResult
### Community 599 - "Community 599"
Cohesion: 0.67
@@ -2668,8 +2694,8 @@ Cohesion: 0.67
Nodes (3): نقاط ضعف, نقاط قوت, ۶. تحلیل API Design
### Community 606 - "Community 606"
Cohesion: 0.40
Nodes (5): DELETE `/api/v1/billing/tenant-insurances/{uuid}`, GET `/api/v1/billing/tenant-insurances`, PATCH `/api/v1/billing/tenant-insurances/{uuid}`, POST `/api/v1/billing/tenant-insurances`, TenantInsurance — قراردادهای بیمه‌ی tenant (فاز ۱ سیستم صورتحساب)
Cohesion: 0.25
Nodes (8): ثبت‌نام دکتر — از طریق نماینده, ثبت‌نام دکتر — از طریق کلینیک, ثبت‌نام دکتر — مستقل, ۱. معرفی محصول, ۱.۱ نقش‌های سیستم, ۱.۲ فلوهای عملیاتی اصلی, ۱.۳ پلن‌های اشتراک, ۱.۴ سیستم پیامک
### Community 607 - "Community 607"
Cohesion: 0.39
@@ -2680,8 +2706,8 @@ Cohesion: 0.67
Nodes (3): بک‌اند, فرانت‌اند, وضعیت فعلی کد (مهم — قبل از تغییر بخوان)
### Community 618 - "Community 618"
Cohesion: 0.12
Nodes (6): ServiceCoverageNPlusOneTest, TenantInsuranceCleanupTest, TenantServiceCoverageRepository, TenantInsuranceCleanupService, ManagerRegistry, TenantServiceCoverage
Cohesion: 0.16
Nodes (5): ServiceItemDeleteCleanupTest, ServiceCoverageNPlusOneTest, TenantServiceCoverageRepository, ManagerRegistry, TenantServiceCoverage
### Community 631 - "Community 631"
Cohesion: 0.50
@@ -2696,28 +2722,24 @@ Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/doctor/{uuid}`, Path Parameters, Response `200`
### Community 634 - "Community 634"
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/admin/insurances`, Query Parameters, Response `200`
Cohesion: 0.25
Nodes (8): ۲.۲ انواع دسته‌بندی (Category Types), ۲.۲.۱ تگ (Tag), ۲.۲.۲ استان (State), ۲.۲.۳ شهر (City), ۲.۲.۴ بیمه پایه (Basic Insurance), ۲.۲.۵ بیمه مکمل (Supplementary Insurance), ۲.۲.۶ تخصص دکتر (Doctor Specialty), ۲.۲.۷ خدمات دکتر (Doctor Services)
### Community 635 - "Community 635"
Cohesion: 0.50
Nodes (4): Errors, PATCH `/api/v1/admin/insurance/{id}`, Path Parameters, Response `200`
Cohesion: 0.43
Nodes (5): BeforeInstallPromptEvent, usePwaInstall(), PwaInstallBanner(), detectIOS(), PwaLoginCard()
### Community 636 - "Community 636"
Cohesion: 0.48
Nodes (3): SmsSettingsRepository, SmsSettings, ManagerRegistry
### Community 638 - "Community 638"
Cohesion: 0.67
Nodes (3): GET `/api/v1/clinic-pro/doctor-addresses/{doctorId}`, Path Parameters, Response `200`
### Community 639 - "Community 639"
Cohesion: 0.67
Nodes (3): GET `/api/v1/billing/tenant-insurances/{uuid}/service-coverage`, PUT `/api/v1/billing/tenant-insurances/{uuid}/service-coverage`, TenantServiceCoverage — پوشش خدمت تحت یک قرارداد بیمه (فاز ۲)
### Community 640 - "Community 640"
Cohesion: 0.67
Nodes (3): GET `/api/v1/insurances`, Query Parameters, Response `200`
### Community 641 - "Community 641"
Cohesion: 0.67
Nodes (3): POST `/api/v1/admin/insurance/{id}/upload-logo`, Request, Response `200`
Cohesion: 0.33
Nodes (6): GET /api/v1/sms/balance — موجودی حساب پیامک, POST /api/v1/sms/queue — افزودن به صف, ۴. سیستم حساب و صف پیامک, ۴.۱ حساب پیامک (SMS Account), ۴.۲ صف پیامک (SMS Queue), ۴.۳ API پیامک
### Community 646 - "Community 646"
Cohesion: 0.40
@@ -2728,12 +2750,12 @@ Cohesion: 0.40
Nodes (5): 41. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 649 - "Community 649"
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/secretaries`, Query Parameters, Response `200`, Secretary Management
Cohesion: 0.40
Nodes (5): 31. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 650 - "Community 650"
Cohesion: 0.50
Nodes (4): extra, symfony, allow-contrib, require
Cohesion: 0.40
Nodes (5): 32. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 651 - "Community 651"
Cohesion: 0.53
@@ -2751,33 +2773,105 @@ Nodes (4): 38. 🟢 `GET` Unapproved comments, هدرهای اضافی, پارا
Cohesion: 0.50
Nodes (4): 44. 🟢 `GET` list comment, هدرهای اضافی, پارامترهای Query, پاسخ‌ها
### Community 655 - "Community 655"
Cohesion: 0.40
Nodes (5): 37. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 656 - "Community 656"
Cohesion: 0.40
Nodes (5): ۲.۸ تنظیمات نوبت (Appointment Settings), ۲.۸.۱ برنامه هفتگی (Weekly Schedule), ۲.۸.۲ تعطیلات (Holidays), ۲.۸.۳ لغو تعطیل (Date Override), ۲.۸.۴ الگوریتم محاسبه اسلات‌های خالی
### Community 657 - "Community 657"
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/payments`, Payment Management, Query Parameters, Response `200`
### Community 658 - "Community 658"
Cohesion: 0.50
Nodes (4): Errors, PATCH `/api/v1/admin/province/{id}`, Path Parameters, Response `200`
### Community 659 - "Community 659"
Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/admin/city`, Request Body (`application/json`), Response `201`
### Community 660 - "Community 660"
Cohesion: 0.50
Nodes (4): 39. 🟡 `PATCH` Comment confirmation, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 661 - "Community 661"
Cohesion: 0.50
Nodes (4): 40. 🔵 `POST` post, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 662 - "Community 662"
Cohesion: 0.50
Nodes (4): Application Logs, GET `/api/v1/admin/logs`, Query Parameters, Response `200`
### Community 664 - "Community 664"
Cohesion: 0.50
Nodes (4): 45. 🔵 `POST` post, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 665 - "Community 665"
Cohesion: 0.50
Nodes (4): 46. 🟡 `PATCH` patch, مثال Request, هدرهای اضافی, پاسخ‌ها
### Community 666 - "Community 666"
Cohesion: 0.50
Nodes (4): GET /api/v1/appointment-settings/slots — دریافت اسلات‌های خالی, POST /api/v1/appointment-settings/holidays — ثبت تعطیلی (فقط ادمین), POST /api/v1/appointment-settings/overrides — ثبت Override توسط دکتر, Task-09: API تنظیمات نوبت
### Community 667 - "Community 667"
Cohesion: 0.50
Nodes (4): GET /api/v1/categories/cities — شهرها, GET /api/v1/categories/states — استان‌ها, Task-08: API دسته‌بندی‌ها, سایر Endpoint های دسته‌بندی — الزامی
### Community 671 - "Community 671"
Cohesion: 0.50
Nodes (4): ۲.۱۳ نظرات، لایک و امتیازدهی, ۲.۱۳.۱ نظر (Comment), ۲.۱۳.۲ لایک (Like), ۲.۱۳.۳ امتیاز (Rate)
### Community 672 - "Community 672"
Cohesion: 0.50
Nodes (4): GET `/api/v1/admin/settlements`, Query Parameters, Response `200`, Settlement Management
### Community 673 - "Community 673"
Cohesion: 0.67
Nodes (3): GET `/api/v1/admin/cities`, Query Parameters, Response `200`
### Community 674 - "Community 674"
Cohesion: 0.67
Nodes (3): GET `/api/v1/cities`, Query Parameters, Response `200`
### Community 675 - "Community 675"
Cohesion: 0.67
Nodes (3): 34. 🔵 `POST` image logo, هدرهای اضافی, پاسخ‌ها
### Community 676 - "Community 676"
Cohesion: 0.67
Nodes (3): 36. 🟢 `GET` get my rate, هدرهای اضافی, پاسخ‌ها
### Community 677 - "Community 677"
Cohesion: 0.67
Nodes (3): 42. 🔴 `DELETE` delete, هدرهای اضافی, پاسخ‌ها
### Community 678 - "Community 678"
Cohesion: 0.67
Nodes (3): 43. 🟢 `GET` get, هدرهای اضافی, پاسخ‌ها
## Knowledge Gaps
- **3564 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `TenantInsurance`, `CoverageRow`, `Draft` (+3559 more)
- **3640 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `TenantInsurance`, `CoverageRow`, `Draft` (+3635 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **129 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **128 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 `BaseController` connect `Community 108` to `Community 6`, `Community 138`, `Community 139`, `Community 14`, `Community 15`, `Community 275`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 295`, `Community 300`, `Community 301`, `Community 175`, `Community 176`, `Community 177`, `Community 440`, `Community 58`, `Community 59`, `Community 63`, `Community 64`, `Community 70`, `Community 71`, `Community 75`, `Community 206`, `Community 347`, `Community 230`, `Community 103`, `Community 104`, `Community 107`, `Community 109`, `Community 121`, `Community 122`, `Community 252`?**
_High betweenness centrality (0.028) - this node is a cross-community bridge._
- **Why does `ApiTestCase` connect `Community 86` to `Community 609`, `Community 541`, `Community 484`, `Community 574`, `Community 618`, `Community 397`, `Community 495`, `Community 368`, `Community 497`, `Community 594`, `Community 562`, `Community 371`, `Community 565`, `Community 535`, `Community 636`, `Community 573`, `Community 318`, `Community 575`?**
_High betweenness centrality (0.019) - this node is a cross-community bridge._
- **Why does `Version20260614181657` connect `Community 431` to `Community 400`?**
- **Why does `BaseController` connect `Community 108` to `Community 4`, `Community 6`, `Community 138`, `Community 139`, `Community 14`, `Community 15`, `Community 275`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 295`, `Community 300`, `Community 301`, `Community 175`, `Community 176`, `Community 177`, `Community 58`, `Community 59`, `Community 63`, `Community 64`, `Community 70`, `Community 71`, `Community 75`, `Community 206`, `Community 230`, `Community 103`, `Community 104`, `Community 107`, `Community 109`, `Community 121`, `Community 122`, `Community 252`?**
_High betweenness centrality (0.030) - this node is a cross-community bridge._
- **Why does `AppointmentRepository` connect `Community 119` to `Community 53`?**
_High betweenness centrality (0.017) - this node is a cross-community bridge._
- **Why does `Version20260614181657` connect `Community 431` to `Community 399`?**
_High betweenness centrality (0.015) - this node is a cross-community bridge._
- **What connects `ALLOWED_ROLES`, `Pricing`, `TenantInsurance` to the rest of the system?**
_3564 weakly-connected nodes found - possible documentation gaps or missing edges._
_3640 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Community 0` be split into smaller, more focused modules?**
_Cohesion score 0.047107014848950336 - nodes in this community are weakly interconnected._
_Cohesion score 0.05012531328320802 - nodes in this community are weakly interconnected._
- **Should `Community 1` be split into smaller, more focused modules?**
_Cohesion score 0.028985507246376812 - nodes in this community are weakly interconnected._
- **Should `Community 2` be split into smaller, more focused modules?**
_Cohesion score 0.07317073170731707 - nodes in this community are weakly interconnected._
_Cohesion score 0.06280193236714976 - 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
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_src_payment_gateway_paymentgatewayinterface_php", "label": "PaymentGatewayInterface.php", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L1"}, {"id": "gateway_paymentgatewayinterface_getname", "label": "getName()", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L7"}, {"id": "gateway_paymentgatewayinterface_isconfigured", "label": "isConfigured()", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L12"}, {"id": "gateway_paymentgatewayinterface_initiate", "label": "initiate()", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L17"}, {"id": "paymentinitresult", "label": "PaymentInitResult", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L17"}, {"id": "gateway_paymentgatewayinterface_verify", "label": "verify()", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L22"}, {"id": "paymentverifyresult", "label": "PaymentVerifyResult", "file_type": "code", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L22"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_payment_gateway_paymentgatewayinterface_php", "target": "gateway_paymentgatewayinterface_getname", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_payment_gateway_paymentgatewayinterface_php", "target": "gateway_paymentgatewayinterface_isconfigured", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L12", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_payment_gateway_paymentgatewayinterface_php", "target": "gateway_paymentgatewayinterface_initiate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L17", "weight": 1.0}, {"source": "gateway_paymentgatewayinterface_initiate", "target": "paymentinitresult", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L17", "weight": 1.0, "context": "return_type"}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_payment_gateway_paymentgatewayinterface_php", "target": "gateway_paymentgatewayinterface_verify", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L22", "weight": 1.0}, {"source": "gateway_paymentgatewayinterface_verify", "target": "paymentverifyresult", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/PaymentGatewayInterface.php", "source_location": "L22", "weight": 1.0, "context": "return_type"}], "raw_calls": []}
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_src_payment_gateway_mockgateway_php", "label": "MockGateway.php", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L1"}, {"id": "gateway_mockgateway_mockgateway", "label": "MockGateway", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L5"}, {"id": "paymentgatewayinterface", "label": "PaymentGatewayInterface", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "gateway_mockgateway_mockgateway_getname", "label": ".getName()", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L7"}, {"id": "gateway_mockgateway_mockgateway_isconfigured", "label": ".isConfigured()", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L9"}, {"id": "gateway_mockgateway_mockgateway_initiate", "label": ".initiate()", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L11"}, {"id": "paymentinitresult", "label": "PaymentInitResult", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L11"}, {"id": "gateway_mockgateway_mockgateway_verify", "label": ".verify()", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L17"}, {"id": "paymentverifyresult", "label": "PaymentVerifyResult", "file_type": "code", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L17"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_payment_gateway_mockgateway_php", "target": "gateway_mockgateway_mockgateway", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L5", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway", "target": "paymentgatewayinterface", "relation": "implements", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L5", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway", "target": "gateway_mockgateway_mockgateway_getname", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L7", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway", "target": "gateway_mockgateway_mockgateway_isconfigured", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L9", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway", "target": "gateway_mockgateway_mockgateway_initiate", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L11", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway_initiate", "target": "paymentinitresult", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L11", "weight": 1.0, "context": "return_type"}, {"source": "gateway_mockgateway_mockgateway", "target": "gateway_mockgateway_mockgateway_verify", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L17", "weight": 1.0}, {"source": "gateway_mockgateway_mockgateway_verify", "target": "paymentverifyresult", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Payment/Gateway/MockGateway.php", "source_location": "L17", "weight": 1.0, "context": "return_type"}], "raw_calls": []}
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
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
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
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_src_sms_entity_smslog_php", "label": "SmsLog.php", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L1"}, {"id": "entity_smslog_smslog", "label": "SmsLog", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L9"}, {"id": "entity_smslog_smslog_construct", "label": ".__construct()", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L65"}, {"id": "entity_smslog_smslog_settemplateuuid", "label": ".setTemplateUuid()", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L76"}, {"id": "self", "label": "self", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L76"}, {"id": "entity_smslog_smslog_gettag", "label": ".getTag()", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L77"}, {"id": "entity_smslog_smslog_settag", "label": ".setTag()", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L78"}, {"id": "entity_smslog_smslog_toarray", "label": ".toArray()", "file_type": "code", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L80"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_sms_entity_smslog_php", "target": "mapping", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L5", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_sms_entity_smslog_php", "target": "smslogrepository", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L6", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_sms_entity_smslog_php", "target": "uuid", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_sms_entity_smslog_php", "target": "entity_smslog_smslog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L9", "weight": 1.0}, {"source": "entity_smslog_smslog", "target": "entity_smslog_smslog_construct", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L65", "weight": 1.0}, {"source": "entity_smslog_smslog", "target": "entity_smslog_smslog_settemplateuuid", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L76", "weight": 1.0}, {"source": "entity_smslog_smslog_settemplateuuid", "target": "self", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L76", "weight": 1.0, "context": "return_type"}, {"source": "entity_smslog_smslog", "target": "entity_smslog_smslog_gettag", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L77", "weight": 1.0}, {"source": "entity_smslog_smslog", "target": "entity_smslog_smslog_settag", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L78", "weight": 1.0}, {"source": "entity_smslog_smslog_settag", "target": "self", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L78", "weight": 1.0, "context": "return_type"}, {"source": "entity_smslog_smslog", "target": "entity_smslog_smslog_toarray", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Sms/Entity/SmsLog.php", "source_location": "L80", "weight": 1.0}], "raw_calls": [{"caller_nid": "entity_smslog_smslog_construct", "callee": "toRfc4122", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Sms/Entity/SmsLog.php", "source_location": "L67", "receiver": null}, {"caller_nid": "entity_smslog_smslog_construct", "callee": "Uuid", "is_member_call": false, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Sms/Entity/SmsLog.php", "source_location": "L67", "receiver": null}, {"caller_nid": "entity_smslog_smslog_construct", "callee": "time", "is_member_call": false, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Sms/Entity/SmsLog.php", "source_location": "L73", "receiver": null}]}
+1 -1
View File
File diff suppressed because one or more lines are too long
+2983 -888
View File
File diff suppressed because it is too large Load Diff
+91 -66
View File
@@ -50,8 +50,8 @@
"semantic_hash": ""
},
"assets/admin/components/ui/DataTable.tsx": {
"mtime": 1781106808.7261238,
"ast_hash": "2cbc50f8b50ca306376156e71ecd11e0",
"mtime": 1782844471.5008922,
"ast_hash": "66195ae92c42ae390126c7297f7b313d",
"semantic_hash": ""
},
"assets/admin/components/ui/FeatureGate.tsx": {
@@ -135,8 +135,8 @@
"semantic_hash": ""
},
"assets/admin/hooks/usePaymentConfig.ts": {
"mtime": 1781516938.5504773,
"ast_hash": "e252c1261b74d4e8731aeebc89dd1c70",
"mtime": 1782897046.749733,
"ast_hash": "f71056b62ca0ccc9149c93d336053afa",
"semantic_hash": ""
},
"assets/admin/hooks/usePwaInstall.ts": {
@@ -190,8 +190,8 @@
"semantic_hash": ""
},
"assets/admin/pages/CategoriesPage.tsx": {
"mtime": 1782838987.6521325,
"ast_hash": "e4e8f39e7e7a03b947ce2883ed595a37",
"mtime": 1782844707.7293186,
"ast_hash": "a5dab31477ec4359b88f76d40bcb35bf",
"semantic_hash": ""
},
"assets/admin/pages/ClaimsPage.tsx": {
@@ -345,8 +345,8 @@
"semantic_hash": ""
},
"assets/admin/pages/SettingsPage.tsx": {
"mtime": 1782319832.2352676,
"ast_hash": "4f8d36873a0259600edb4c6df585f356",
"mtime": 1782894003.7974715,
"ast_hash": "2916e104ddce46b458010eb2160bfb9a",
"semantic_hash": ""
},
"assets/admin/pages/SettlementDetailPage.tsx": {
@@ -375,8 +375,8 @@
"semantic_hash": ""
},
"assets/admin/pages/SubscriptionPage.tsx": {
"mtime": 1781521748.0909407,
"ast_hash": "e1b5ce2c29dc8b72d8558a7029fde768",
"mtime": 1782897125.5820823,
"ast_hash": "edb160fc9e85f915400426c76610e8c4",
"semantic_hash": ""
},
"assets/admin/pages/UserDetailPage.tsx": {
@@ -1150,8 +1150,8 @@
"semantic_hash": ""
},
"src/Config/Controller/SiteConfigController.php": {
"mtime": 1782319753.4996316,
"ast_hash": "ee22114d1ceb9a3c78dbbcc5f1ff00ce",
"mtime": 1782893916.7348526,
"ast_hash": "cb994abce239f65aa6ea56e240beaaf9",
"semantic_hash": ""
},
"src/Config/Entity/SiteConfig.php": {
@@ -1165,8 +1165,8 @@
"semantic_hash": ""
},
"src/Config/Repository/SiteConfigRepository.php": {
"mtime": 1782319853.8285086,
"ast_hash": "a36b1f176fdffd7494eab5ca95c1994c",
"mtime": 1782893889.148054,
"ast_hash": "fafe887c5ba8de7a9185969f028a79d9",
"semantic_hash": ""
},
"src/Config/Repository/TaxRateHistoryRepository.php": {
@@ -1175,8 +1175,8 @@
"semantic_hash": ""
},
"src/Dashboard/Controller/DashboardController.php": {
"mtime": 1781522583.7337224,
"ast_hash": "15596779638e99e2edfd7c06d6b95c1e",
"mtime": 1782895903.5178185,
"ast_hash": "8f4817a710736a74b1bb317fafc58614",
"semantic_hash": ""
},
"src/Doctor/Controller/DoctorController.php": {
@@ -1205,8 +1205,8 @@
"semantic_hash": ""
},
"src/DoctorService/Controller/DoctorServiceController.php": {
"mtime": 1781522583.7325408,
"ast_hash": "af0d4cbed07d0ce02335a56dbe487b62",
"mtime": 1782844356.1675708,
"ast_hash": "3646bb6c12f6457448041a44b735fe8c",
"semantic_hash": ""
},
"src/DoctorService/Entity/DoctorService.php": {
@@ -1220,8 +1220,8 @@
"semantic_hash": ""
},
"src/Insurance/Controller/InsuranceController.php": {
"mtime": 1782728407.196781,
"ast_hash": "dfd2f646daaa51e37e7cda5a5ee4bb6b",
"mtime": 1782844375.1354241,
"ast_hash": "8ddef824ed781bfe74e169ff3084677c",
"semantic_hash": ""
},
"src/Insurance/Entity/DoctorInsurance.php": {
@@ -1295,8 +1295,8 @@
"semantic_hash": ""
},
"src/Location/Controller/LocationController.php": {
"mtime": 1781522583.7341,
"ast_hash": "a966ca5c350f63adb7beb8031a79f85f",
"mtime": 1782844299.834749,
"ast_hash": "6a1296178827cdc99c6775db563c41f0",
"semantic_hash": ""
},
"src/Location/Entity/City.php": {
@@ -1360,8 +1360,8 @@
"semantic_hash": ""
},
"src/Payment/Controller/PaymentController.php": {
"mtime": 1782728407.1982014,
"ast_hash": "d5a27f54ec1c8e8b2fe60a882f057d3d",
"mtime": 1782896983.4736924,
"ast_hash": "da4dadd9532dda783eb589c368f18801",
"semantic_hash": ""
},
"src/Payment/Entity/Payment.php": {
@@ -1370,18 +1370,18 @@
"semantic_hash": ""
},
"src/Payment/Gateway/MellatGateway.php": {
"mtime": 1782750018.5149405,
"ast_hash": "0f96d01c7e17a2894388f74825a232b3",
"mtime": 1782896964.9076507,
"ast_hash": "67b1f4180e7bc36425229c9a9c1f2fa7",
"semantic_hash": ""
},
"src/Payment/Gateway/MockGateway.php": {
"mtime": 1782728407.1989012,
"ast_hash": "af7b427acbde56329bbaf52ba04cbc16",
"mtime": 1782896968.6033201,
"ast_hash": "69fbe77ed2ae3a608171039dc1c70b97",
"semantic_hash": ""
},
"src/Payment/Gateway/PaymentGatewayInterface.php": {
"mtime": 1781012928.7423482,
"ast_hash": "172d5a31bedd652818c51e16300809f8",
"mtime": 1782896961.142725,
"ast_hash": "bb1e00f14c34dbf92e95c97d374655b4",
"semantic_hash": ""
},
"src/Payment/Gateway/PaymentInitResult.php": {
@@ -1395,8 +1395,8 @@
"semantic_hash": ""
},
"src/Payment/Gateway/SepGateway.php": {
"mtime": 1782750047.5329745,
"ast_hash": "c08e78093b3efe725e6798c81bf63dd2",
"mtime": 1782896967.2453976,
"ast_hash": "3f729de2819cf3691231152b3f40924a",
"semantic_hash": ""
},
"src/Payment/Repository/PaymentRepository.php": {
@@ -1475,8 +1475,8 @@
"semantic_hash": ""
},
"src/Secretary/Controller/SecretaryController.php": {
"mtime": 1781522583.7368307,
"ast_hash": "43deb96d880f36196e71117be2a303fe",
"mtime": 1782902851.0718935,
"ast_hash": "9cbf2e62e58b071b044dda089612dd4a",
"semantic_hash": ""
},
"src/Secretary/Entity/DoctorSecretary.php": {
@@ -1610,18 +1610,18 @@
"semantic_hash": ""
},
"src/Sms/Controller/SmsWalletController.php": {
"mtime": 1782110309.289352,
"ast_hash": "f0ac5431b3dc6d534cc8e89921db9b63",
"mtime": 1782894791.5387394,
"ast_hash": "6cf62fad0a8d8cfb3831f09c44a2d49c",
"semantic_hash": ""
},
"src/Sms/Entity/SmsLog.php": {
"mtime": 1782650883.6075425,
"ast_hash": "ed15413ebacfb4eb68a3dd360ca71dd5",
"mtime": 1782902823.9580002,
"ast_hash": "42a038068db64c9b94f3ab6f99a51cd8",
"semantic_hash": ""
},
"src/Sms/Entity/SmsMessageTemplate.php": {
"mtime": 1782650883.608437,
"ast_hash": "80e121593117667abfa485ca75db50b9",
"mtime": 1782902828.6619399,
"ast_hash": "0c8f32c4fab56c8d392dfe11c937c9a3",
"semantic_hash": ""
},
"src/Sms/Entity/SmsSettings.php": {
@@ -1650,8 +1650,8 @@
"semantic_hash": ""
},
"src/Sms/Provider/KavehNegarProvider.php": {
"mtime": 1782749956.4059756,
"ast_hash": "fd66bf9a71b06d16beebf133d8f8a847",
"mtime": 1782893881.0959284,
"ast_hash": "53cc58e643103610cd94b9345b0ffb39",
"semantic_hash": ""
},
"src/Sms/Provider/RanginehProvider.php": {
@@ -1715,8 +1715,8 @@
"semantic_hash": ""
},
"src/Specialty/Controller/SpecialtyController.php": {
"mtime": 1781636247.0767584,
"ast_hash": "7dd13db2726ecf50e95a0bd3f30138d0",
"mtime": 1782844333.7139277,
"ast_hash": "70f51cf45c69597db2ef7f0ef4d70143",
"semantic_hash": ""
},
"src/Specialty/Entity/Specialty.php": {
@@ -1785,8 +1785,8 @@
"semantic_hash": ""
},
"src/Tag/Controller/TagController.php": {
"mtime": 1781522583.7362611,
"ast_hash": "f018e7f0c5ef515f69bf8de5124730f3",
"mtime": 1782844396.159141,
"ast_hash": "df774affd64bf2ff8464a26a44ec813a",
"semantic_hash": ""
},
"src/Tag/Entity/Tag.php": {
@@ -2185,8 +2185,8 @@
"semantic_hash": ""
},
"README.MD": {
"mtime": 1781782021.0983558,
"ast_hash": "1c377bc406f512817799035b93a8c75f",
"mtime": 1782845053.6544068,
"ast_hash": "57c7558eea01b735b714575a461ee751",
"semantic_hash": ""
},
"TEST_USERS.md": {
@@ -2300,8 +2300,8 @@
"semantic_hash": ""
},
"config/services.yaml": {
"mtime": 1782843927.2499301,
"ast_hash": "6ddd0cb49e2be3c0d29348e843166ed1",
"mtime": 1782902861.3039489,
"ast_hash": "0cd5b457c6df19eb90acd03c130bd713",
"semantic_hash": ""
},
"docs/Architecture_Audit.md": {
@@ -2390,8 +2390,8 @@
"semantic_hash": ""
},
"docs/api/doctor-service.md": {
"mtime": 1782839237.8086488,
"ast_hash": "3c3f4da25682c21bf769a2c170b9dc6f",
"mtime": 1782844893.6804142,
"ast_hash": "513b9a4f7674d8b749eb46efbe277797",
"semantic_hash": ""
},
"docs/api/doctor.md": {
@@ -2400,13 +2400,13 @@
"semantic_hash": ""
},
"docs/api/insurance.md": {
"mtime": 1782839237.8089066,
"ast_hash": "66c99e8593c6e48fbbb065610b626e68",
"mtime": 1782844893.6809301,
"ast_hash": "9d6d21db0004b0e780025123ea3a63c9",
"semantic_hash": ""
},
"docs/api/location.md": {
"mtime": 1782839237.808474,
"ast_hash": "9db8856184fd38eed6f377ac425584fa",
"mtime": 1782844893.6796494,
"ast_hash": "bd93b9cdb9c60259814f49193b6cab77",
"semantic_hash": ""
},
"docs/api/patient.md": {
@@ -2415,8 +2415,8 @@
"semantic_hash": ""
},
"docs/api/payment.md": {
"mtime": 1782728407.1095557,
"ast_hash": "599a89165ddf5f33daeb04a6d97a3b5a",
"mtime": 1782897235.6571848,
"ast_hash": "839fec75d0238c39881d9339c26ad43e",
"semantic_hash": ""
},
"docs/api/rating.md": {
@@ -2430,8 +2430,8 @@
"semantic_hash": ""
},
"docs/api/secretary.md": {
"mtime": 1781520442.059899,
"ast_hash": "5b095b626c415a5040be915cce3e0da0",
"mtime": 1782902968.2934825,
"ast_hash": "15b4e6808419e91bc4a7a80b3c528813",
"semantic_hash": ""
},
"docs/api/settlement.md": {
@@ -2440,13 +2440,13 @@
"semantic_hash": ""
},
"docs/api/sms.md": {
"mtime": 1782367200.5063455,
"ast_hash": "613eaa742d3ca4a72845425c46ad546c",
"mtime": 1782902976.009701,
"ast_hash": "2654051c73dddf1e702d686ef5790a47",
"semantic_hash": ""
},
"docs/api/specialty.md": {
"mtime": 1782839237.8082483,
"ast_hash": "45c0b1034a9e6bd3ea4973796b5538c1",
"mtime": 1782844893.6802263,
"ast_hash": "7dd9e75c13f557620e04a3d04cf58140",
"semantic_hash": ""
},
"docs/api/staff.md": {
@@ -2460,8 +2460,8 @@
"semantic_hash": ""
},
"docs/api/tag.md": {
"mtime": 1782839237.8090699,
"ast_hash": "0f848b663c3d80081a71fb46b8088c87",
"mtime": 1782844893.6810575,
"ast_hash": "7b0cd30025e12582e9fa5af37d10d9fb",
"semantic_hash": ""
},
"docs/api/user-profile.md": {
@@ -3458,5 +3458,30 @@
"mtime": 1782843813.8434396,
"ast_hash": "47a348a1a7cf97da5de81caad5f026d9",
"semantic_hash": ""
},
".claude/prompt/production-fixes-cors-payment-gateways.md": {
"mtime": 1782896794.1745296,
"ast_hash": "d16b27e408fa695d271b021c754ac78a",
"semantic_hash": ""
},
".claude/prompt/qa-full-system-audit.md": {
"mtime": 1782894418.0248322,
"ast_hash": "8d2eda6fd68cc8886bfbfe71cb74a7d4",
"semantic_hash": ""
},
".claude/prompt/secretary-welcome-sms.md": {
"mtime": 1782902722.286387,
"ast_hash": "f98cb6bc9719953fb2a4cae0ba1c3531",
"semantic_hash": ""
},
".claude/prompt/sms-settings-apikey-env-only.md": {
"mtime": 1782893768.6085784,
"ast_hash": "0563289f277db924b6228fad067b0e32",
"semantic_hash": ""
},
"docs/qa/full-system-audit-report.md": {
"mtime": 1782896060.8114219,
"ast_hash": "9d1436d8787330a1cb06c54c4e896069",
"semantic_hash": ""
}
}
@@ -10,6 +10,9 @@ use App\Secretary\Entity\DoctorSecretary;
use App\Secretary\Repository\DoctorSecretaryRepository;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
use App\Sms\Entity\SmsLog;
use App\Sms\Service\SmsService;
use App\Sms\Service\SmsTextResolver;
use App\Subscription\Service\SubscriptionService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -30,6 +33,9 @@ class SecretaryController extends BaseController
private readonly UserRepository $userRepo,
private readonly UserPasswordHasherInterface $hasher,
private readonly SubscriptionService $subscriptionService,
private readonly SmsService $smsService,
private readonly SmsTextResolver $smsText,
private readonly string $appUrl,
) {}
#[Route('/api/v1/secretary', methods: ['POST'])]
@@ -110,9 +116,29 @@ class SecretaryController extends BaseController
$this->secretaryRepo->save($secretary);
$this->sendWelcomeSms($mobile, $doctor, $ownerClinic);
return $this->success(['data' => $secretary->toArray()], 201);
}
/** پیامک خوش‌آمد به منشی تازه‌تعریف‌شده — متن از template تگ TAG_SECRETARY */
private function sendWelcomeSms(string $mobile, $doctor, $ownerClinic): void
{
$ownerName = $ownerClinic !== null
? ($ownerClinic->getName() ?? 'کلینیک')
: ($doctor->getUser()->getRealName() ?? 'پزشک');
$link = rtrim($this->appUrl, '/') . '/login';
$message = $this->smsText->resolve(SmsLog::TAG_SECRETARY, [
'owner' => $ownerName,
'username' => $mobile,
'link' => $link,
]);
$this->smsService->dispatchAsync($mobile, $message, tag: SmsLog::TAG_SECRETARY);
}
#[Route('/api/v1/secretary/{uuid}', methods: ['GET'])]
public function show(string $uuid, #[CurrentUser] User $currentUser): JsonResponse
{
+2
View File
@@ -19,6 +19,7 @@ class SmsLog
public const TAG_NOTIFICATION_MOBILE = 'notification_mobile';
public const TAG_USER_TEMPLATE = 'user_template';
public const TAG_WELCOME = 'welcome';
public const TAG_SECRETARY = 'secretary';
public const TAGS = [
self::TAG_GLOBAL,
@@ -29,6 +30,7 @@ class SmsLog
self::TAG_NOTIFICATION_MOBILE,
self::TAG_USER_TEMPLATE,
self::TAG_WELCOME,
self::TAG_SECRETARY,
];
#[ORM\Id]
+5
View File
@@ -43,6 +43,11 @@ class SmsMessageTemplate
'body' => "کد تأیید شماره اعلان شما: {code}\nاعتبار: ۵ دقیقه",
'variables' => ['code'],
],
SmsLog::TAG_SECRETARY => [
'title' => 'دعوت به‌عنوان منشی',
'body' => "شما به‌عنوان منشیِ {owner} در کلینیک‌پرو تعریف شدید.\nشماره‌کاربری: {username}\nلینک ورود: {link}",
'variables' => ['owner', 'username', 'link'],
],
];
#[ORM\Id]