Add AST cache for AdminLogsTest.php with extracted nodes and edges
This commit is contained in:
@@ -83,8 +83,42 @@ export const api = {
|
||||
put: <T>(path: string, body: unknown) =>
|
||||
request<T>(path, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
delete: <T>(path: string) => request<T>(path, { method: 'DELETE' }),
|
||||
download: (path: string) => downloadFile(path),
|
||||
};
|
||||
|
||||
// دانلود فایل با ارسال توکن JWT در هدر و ذخیره روی دیسک کاربر
|
||||
async function downloadFile(path: string, retry = true): Promise<void> {
|
||||
const token = getToken();
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||
|
||||
const res = await fetch(`${BASE_URL}${path}`, { headers });
|
||||
|
||||
if (!res.ok) {
|
||||
if (res.status === 401 && retry) {
|
||||
const newToken = await refreshOnce();
|
||||
if (newToken) return downloadFile(path, false);
|
||||
useAuthStore.getState().logout();
|
||||
window.location.replace('/admin/login');
|
||||
}
|
||||
throw new ApiError(res.status, 'ERR_DOWNLOAD', 'دانلود ناموفق بود');
|
||||
}
|
||||
|
||||
const blob = await res.blob();
|
||||
const disposition = res.headers.get('Content-Disposition') ?? '';
|
||||
const match = disposition.match(/filename="?([^"]+)"?/);
|
||||
const filename = match ? match[1] : 'download';
|
||||
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
success: boolean;
|
||||
data: T;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { TrashIcon } from '@heroicons/react/24/outline';
|
||||
import { TrashIcon, ArrowDownTrayIcon } from '@heroicons/react/24/outline';
|
||||
import { api } from '../lib/api';
|
||||
import type { PaginatedResponse, ApiResponse } from '../lib/api';
|
||||
import type { AppLog } from '../types';
|
||||
@@ -38,9 +38,22 @@ export default function LogsPage() {
|
||||
const [search, setSearch] = useState('');
|
||||
const [viewLog, setViewLog] = useState<AppLog | null>(null);
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
const [downloading, setDownloading] = useState(false);
|
||||
const limit = 25;
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const handleDownload = async () => {
|
||||
setDownloading(true);
|
||||
try {
|
||||
const qs =
|
||||
(level ? `&level=${level}` : '') +
|
||||
(search ? `&search=${encodeURIComponent(search)}` : '');
|
||||
await api.download(`/api/v1/admin/logs/export?${qs}`);
|
||||
} finally {
|
||||
setDownloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const logsQuery = useQuery({
|
||||
queryKey: ['admin-logs', page, level, search],
|
||||
queryFn: () =>
|
||||
@@ -95,14 +108,24 @@ export default function LogsPage() {
|
||||
<div className="muted">رویدادهای ثبتشدهی سیستم (اخطار و بالاتر)</div>
|
||||
</div>
|
||||
{tab === 'logs' && (
|
||||
<button
|
||||
className="btn danger sm"
|
||||
onClick={() => setConfirmClear(true)}
|
||||
disabled={(logsQuery.data?.meta?.totalRecords ?? 0) === 0}
|
||||
>
|
||||
<TrashIcon style={{ width: 16, height: 16 }} />
|
||||
حذف همه لاگها
|
||||
</button>
|
||||
<div style={{ display: 'flex', gap: 8 }}>
|
||||
<button
|
||||
className="btn ghost sm"
|
||||
onClick={handleDownload}
|
||||
disabled={downloading || (logsQuery.data?.meta?.totalRecords ?? 0) === 0}
|
||||
>
|
||||
<ArrowDownTrayIcon style={{ width: 16, height: 16 }} />
|
||||
{downloading ? 'در حال دانلود...' : 'دانلود همه لاگها'}
|
||||
</button>
|
||||
<button
|
||||
className="btn danger sm"
|
||||
onClick={() => setConfirmClear(true)}
|
||||
disabled={(logsQuery.data?.meta?.totalRecords ?? 0) === 0}
|
||||
>
|
||||
<TrashIcon style={{ width: 16, height: 16 }} />
|
||||
حذف همه لاگها
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1216,6 +1216,25 @@ Notes:
|
||||
- `context` is a JSON string (or `null`); a `Throwable` in the context is stored as a compact `Class: message @ file:line` string, never the raw object.
|
||||
- `created_at` is a Unix timestamp (integer).
|
||||
|
||||
### GET `/api/v1/admin/logs/export`
|
||||
|
||||
Export **all** matching logs as a CSV file (no pagination). Respects the same `level`, `search`, `from`, `to` filters as the list endpoint. Ordered newest first (`id DESC`).
|
||||
|
||||
**Permission:** `ROLE_ADMIN`
|
||||
|
||||
### Query Parameters
|
||||
| Param | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `level` | string | ❌ | Exact PSR level: `warning`, `error`, `critical`, `alert`, `emergency` |
|
||||
| `search` | string | ❌ | Substring match on the message |
|
||||
| `from` | integer | ❌ | Unix timestamp lower bound (`created_at >=`) |
|
||||
| `to` | integer | ❌ | Unix timestamp upper bound (`created_at <=`) |
|
||||
|
||||
#### Response `200`
|
||||
- `Content-Type: text/csv; charset=UTF-8`
|
||||
- `Content-Disposition: attachment; filename="logs-YYYYMMDD-HHMMSS.csv"`
|
||||
- Streamed CSV with a UTF-8 BOM (Excel-friendly for Persian). Columns: `id, level, message, context, channel, path, created_at`. `created_at` is formatted as `Y-m-d H:i:s`.
|
||||
|
||||
### DELETE `/api/v1/admin/logs`
|
||||
|
||||
Delete **all** persisted logs (truncate the `app_log` table). Irreversible.
|
||||
|
||||
@@ -693,37 +693,26 @@
|
||||
"691": "Community 691",
|
||||
"692": "Community 692",
|
||||
"693": "Community 693",
|
||||
"694": "Community 694",
|
||||
"695": "Community 695",
|
||||
"696": "Community 696",
|
||||
"697": "Community 697",
|
||||
"698": "Community 698",
|
||||
"699": "Community 699",
|
||||
"700": "Community 700",
|
||||
"701": "Community 701",
|
||||
"702": "Community 702",
|
||||
"703": "Community 703",
|
||||
"704": "Community 704",
|
||||
"705": "Community 705",
|
||||
"706": "Community 706",
|
||||
"707": "Community 707",
|
||||
"708": "Community 708",
|
||||
"709": "Community 709",
|
||||
"710": "Community 710",
|
||||
"711": "Community 711",
|
||||
"712": "Community 712",
|
||||
"713": "Community 713",
|
||||
"714": "Community 714",
|
||||
"715": "Community 715",
|
||||
"716": "Community 716",
|
||||
"717": "Community 717",
|
||||
"718": "Community 718",
|
||||
"719": "Community 719",
|
||||
"720": "Community 720",
|
||||
"721": "Community 721",
|
||||
"722": "Community 722",
|
||||
"723": "Community 723",
|
||||
"724": "Community 724",
|
||||
"725": "Community 725",
|
||||
"726": "Community 726",
|
||||
"727": "Community 727",
|
||||
@@ -731,9 +720,5 @@
|
||||
"729": "Community 729",
|
||||
"730": "Community 730",
|
||||
"731": "Community 731",
|
||||
"732": "Community 732",
|
||||
"733": "Community 733",
|
||||
"734": "Community 734",
|
||||
"735": "Community 735",
|
||||
"738": "Community 738"
|
||||
}
|
||||
|
||||
+125
-176
@@ -1,16 +1,16 @@
|
||||
# Graph Report - clinicpro (2026-07-09)
|
||||
# Graph Report - clinicpro (2026-07-10)
|
||||
|
||||
## Corpus Check
|
||||
- 728 files · ~537,442 words
|
||||
- 728 files · ~538,154 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 9196 nodes · 12725 edges · 737 communities (586 shown, 151 thin omitted)
|
||||
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 278 edges (avg confidence: 0.8)
|
||||
- 9204 nodes · 12739 edges · 722 communities (577 shown, 145 thin omitted)
|
||||
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 279 edges (avg confidence: 0.8)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Graph Freshness
|
||||
- Built from commit: `0750bc98`
|
||||
- Built from commit: `9d2023a7`
|
||||
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
|
||||
- Run `graphify update .` after code changes (no API cost).
|
||||
|
||||
@@ -694,37 +694,26 @@
|
||||
- [[_COMMUNITY_Community 691|Community 691]]
|
||||
- [[_COMMUNITY_Community 692|Community 692]]
|
||||
- [[_COMMUNITY_Community 693|Community 693]]
|
||||
- [[_COMMUNITY_Community 694|Community 694]]
|
||||
- [[_COMMUNITY_Community 695|Community 695]]
|
||||
- [[_COMMUNITY_Community 696|Community 696]]
|
||||
- [[_COMMUNITY_Community 697|Community 697]]
|
||||
- [[_COMMUNITY_Community 698|Community 698]]
|
||||
- [[_COMMUNITY_Community 699|Community 699]]
|
||||
- [[_COMMUNITY_Community 700|Community 700]]
|
||||
- [[_COMMUNITY_Community 701|Community 701]]
|
||||
- [[_COMMUNITY_Community 702|Community 702]]
|
||||
- [[_COMMUNITY_Community 703|Community 703]]
|
||||
- [[_COMMUNITY_Community 704|Community 704]]
|
||||
- [[_COMMUNITY_Community 705|Community 705]]
|
||||
- [[_COMMUNITY_Community 706|Community 706]]
|
||||
- [[_COMMUNITY_Community 707|Community 707]]
|
||||
- [[_COMMUNITY_Community 708|Community 708]]
|
||||
- [[_COMMUNITY_Community 709|Community 709]]
|
||||
- [[_COMMUNITY_Community 710|Community 710]]
|
||||
- [[_COMMUNITY_Community 711|Community 711]]
|
||||
- [[_COMMUNITY_Community 712|Community 712]]
|
||||
- [[_COMMUNITY_Community 713|Community 713]]
|
||||
- [[_COMMUNITY_Community 714|Community 714]]
|
||||
- [[_COMMUNITY_Community 715|Community 715]]
|
||||
- [[_COMMUNITY_Community 716|Community 716]]
|
||||
- [[_COMMUNITY_Community 717|Community 717]]
|
||||
- [[_COMMUNITY_Community 718|Community 718]]
|
||||
- [[_COMMUNITY_Community 719|Community 719]]
|
||||
- [[_COMMUNITY_Community 720|Community 720]]
|
||||
- [[_COMMUNITY_Community 721|Community 721]]
|
||||
- [[_COMMUNITY_Community 722|Community 722]]
|
||||
- [[_COMMUNITY_Community 723|Community 723]]
|
||||
- [[_COMMUNITY_Community 724|Community 724]]
|
||||
- [[_COMMUNITY_Community 725|Community 725]]
|
||||
- [[_COMMUNITY_Community 726|Community 726]]
|
||||
- [[_COMMUNITY_Community 727|Community 727]]
|
||||
@@ -732,10 +721,6 @@
|
||||
- [[_COMMUNITY_Community 729|Community 729]]
|
||||
- [[_COMMUNITY_Community 730|Community 730]]
|
||||
- [[_COMMUNITY_Community 731|Community 731]]
|
||||
- [[_COMMUNITY_Community 732|Community 732]]
|
||||
- [[_COMMUNITY_Community 733|Community 733]]
|
||||
- [[_COMMUNITY_Community 734|Community 734]]
|
||||
- [[_COMMUNITY_Community 735|Community 735]]
|
||||
- [[_COMMUNITY_Community 738|Community 738]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
@@ -747,29 +732,29 @@
|
||||
6. `Doctor` - 48 edges
|
||||
7. `useAuthStore` - 43 edges
|
||||
8. `ApiResponse` - 41 edges
|
||||
9. `AdminApiController` - 40 edges
|
||||
9. `AdminApiController` - 41 edges
|
||||
10. `formatDate()` - 39 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `ServiceTariffModal()` --calls--> `formatNumber()` [EXTRACTED]
|
||||
assets/admin/components/ServiceTariffModal.tsx → assets/admin/lib/utils.ts
|
||||
- `Pagination()` --calls--> `formatNumber()` [EXTRACTED]
|
||||
assets/admin/components/ui/Pagination.tsx → assets/admin/lib/utils.ts
|
||||
- `RepresentationSettlementPage()` --calls--> `formatRial()` [EXTRACTED]
|
||||
assets/admin/pages/RepresentationSettlementPage.tsx → assets/admin/lib/utils.ts
|
||||
- `SettlementsPage()` --calls--> `formatRial()` [EXTRACTED]
|
||||
assets/admin/pages/SettlementsPage.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
|
||||
- `LogoUploadField()` --calls--> `useAuthStore` [EXTRACTED]
|
||||
assets/admin/pages/CategoriesPage.tsx → assets/admin/stores/authStore.ts
|
||||
- `TabActions()` --calls--> `useAuthStore` [EXTRACTED]
|
||||
assets/admin/pages/CategoriesPage.tsx → assets/admin/stores/authStore.ts
|
||||
|
||||
## Import Cycles
|
||||
- None detected.
|
||||
|
||||
## Communities (737 total, 151 thin omitted)
|
||||
## Communities (722 total, 145 thin omitted)
|
||||
|
||||
### Community 0 - "Community 0"
|
||||
Cohesion: 0.05
|
||||
Nodes (38): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, DEGREE_OPTIONS, DoctorFormPage() (+30 more)
|
||||
Nodes (48): ALLOWED_ROLES, PrivateRoute(), PublicRoute(), RoleRoute(), queryClient, toastStyle, get, BeforeInstallPromptEvent (+40 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.03
|
||||
@@ -800,8 +785,8 @@ Cohesion: 0.07
|
||||
Nodes (5): Clinic, Collection, Doctor, self, User
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.08
|
||||
Nodes (27): useSubscription(), AdminLayout(), avatarBg(), buildSections(), HUES, Props, ROLE_LABELS, Section (+19 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (27): Contract, InsuranceOption, KIND_LABEL, AdminLayout(), Topbar(), DEGREE_OPTIONS, DoctorFormPage(), FormValues (+19 more)
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.04
|
||||
@@ -820,8 +805,8 @@ 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.07
|
||||
Nodes (25): get, api, ApiError, getToken(), refreshOnce(), request(), { refreshMock, logoutMock }, replaceMock (+17 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (21): api, ApiError, downloadFile(), getToken(), refreshOnce(), request(), { refreshMock, logoutMock }, replaceMock (+13 more)
|
||||
|
||||
### Community 14 - "Community 14"
|
||||
Cohesion: 0.10
|
||||
@@ -832,8 +817,8 @@ Cohesion: 0.25
|
||||
Nodes (7): PaymentController, Appointment, JsonResponse, Payment, Request, Response, User
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 0.06
|
||||
Nodes (8): PatientSession, SmsWallet, LogPruneService, Appointment, Collection, PatientRecord, self, SessionService
|
||||
Cohesion: 0.09
|
||||
Nodes (6): PatientSession, Appointment, Collection, PatientRecord, self, SessionService
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 0.05
|
||||
@@ -845,19 +830,19 @@ Nodes (38): API, API, API, API, API, Route, Route, Route (+30 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 0.03
|
||||
Nodes (81): PaginatedResponse, CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, LogoUploadField(), ProvinceForm (+73 more)
|
||||
Nodes (59): CityForm, citySchema, ImportError, InsuranceForm, insuranceSchema, LogoUploadField(), ProvinceForm, provinceSchema (+51 more)
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 0.13
|
||||
Nodes (3): AdminApiController, JsonResponse, Request
|
||||
Nodes (4): AdminApiController, JsonResponse, Request, StreamedResponse
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
Cohesion: 0.04
|
||||
Nodes (59): PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), ApiResponse, formatNumber(), formatRial(), ClinicDetailPage(), AdminCharts (+51 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (34): formatNumber(), ClinicDetailPage(), AdminCharts, AdminDashboard(), AdminRecent, AdminStats, APPT_CLS, APPT_COLOR (+26 more)
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
Cohesion: 0.15
|
||||
Nodes (9): RatingController, Like, LikeRepository, JsonResponse, Request, User, Comment, ManagerRegistry (+1 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (15): RatingController, Like, Rate, CommentListNPlusOneTest, LikeRepository, RateRepository, JsonResponse, Request (+7 more)
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.05
|
||||
@@ -896,8 +881,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.07
|
||||
Nodes (25): CoverageRow, Draft, KIND, TenantInsurance, ServiceTariffModal(), TariffResponse, TariffRow, EMPTY_ITEMS (+17 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (21): CoverageRow, Draft, KIND, TenantInsurance, ServiceTariffModal(), TariffResponse, TariffRow, EMPTY_ITEMS (+13 more)
|
||||
|
||||
### Community 34 - "Community 34"
|
||||
Cohesion: 0.06
|
||||
@@ -927,6 +912,10 @@ Nodes (5): DoctorAddress, City, Doctor, Province, self
|
||||
Cohesion: 0.09
|
||||
Nodes (4): User, PasswordAuthenticatedUserInterface, self, UserInterface
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
Cohesion: 0.07
|
||||
Nodes (29): ApiResponse, PaginatedResponse, STATUS_FILTERS, FILTERS, Breakdown, SOURCE_LABEL, Summary, LEVEL_FILTER_OPTIONS (+21 more)
|
||||
|
||||
### Community 42 - "Community 42"
|
||||
Cohesion: 0.07
|
||||
Nodes (29): API calls (با `useMutation`):, API موجود:, Frontend موجود:, `PATCH /api/v1/clinic/{clinicUuid}/doctor/{doctorUuid}/deactivate`, `PATCH /api/v1/clinic/{clinicUuid}/doctor/{doctorUuid}/reactivate`, UX نکات:, آپدیت `GET /api/v1/clinic/doctor-list/{clinicUuid}` (فیلدهای جدید), آپدیت interface: (+21 more)
|
||||
@@ -956,8 +945,8 @@ Cohesion: 0.11
|
||||
Nodes (4): Payment, Appointment, self, User
|
||||
|
||||
### Community 49 - "Community 49"
|
||||
Cohesion: 0.09
|
||||
Nodes (18): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+10 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (22): AppointmentsPage(), BookingSlot, CancelledBadge(), DateNavigator(), EMPTY_ARR, getPersianWeekDay(), navBtnSx, NewAppointmentModal() (+14 more)
|
||||
|
||||
### Community 50 - "Community 50"
|
||||
Cohesion: 0.07
|
||||
@@ -972,8 +961,8 @@ Cohesion: 0.07
|
||||
Nodes (26): الزامات UI, باگفیکس صفحه نوبتها, باگ ۱ — کرش تقویم, باگ ۲ — روز هفته در DateNavigator, باگ ۳ — پیام «slot نیست», باگ ۴ — نوبت جدید: نام اجباری + find-or-create patient, باگ ۵ — patient_mobile نشان میدهد موبایل پزشک, باگ ۶ — نوبتهای رزرو شده در نمایش زمانبندی (+18 more)
|
||||
|
||||
### Community 53 - "Community 53"
|
||||
Cohesion: 0.10
|
||||
Nodes (13): AppLogRepository, ClaimItemRepository, DoctorInsuranceRepository, InvoiceRepository, PreRegistrationRepository, ServiceEntityRepository, ManagerRegistry, ManagerRegistry (+5 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (15): AppLogRepository, ClaimItemRepository, InvoiceItemRepository, PreRegistrationRepository, SessionServiceRepository, SiteConfigRepository, ServiceEntityRepository, ManagerRegistry (+7 more)
|
||||
|
||||
### Community 54 - "Community 54"
|
||||
Cohesion: 0.10
|
||||
@@ -992,8 +981,8 @@ Cohesion: 0.08
|
||||
Nodes (24): Blog API, DELETE `/api/v1/blog/{uuid}`, Errors, Errors, Errors, Errors, Errors, GET `/api/v1/blog/{slug}` (+16 more)
|
||||
|
||||
### Community 58 - "Community 58"
|
||||
Cohesion: 0.28
|
||||
Nodes (4): Blog, BlogRepository, ManagerRegistry, QueryBuilder
|
||||
Cohesion: 0.15
|
||||
Nodes (8): Blog, BlogController, BlogRepository, JsonResponse, Request, User, ManagerRegistry, QueryBuilder
|
||||
|
||||
### Community 59 - "Community 59"
|
||||
Cohesion: 0.22
|
||||
@@ -1012,12 +1001,12 @@ Cohesion: 0.08
|
||||
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.09
|
||||
Nodes (20): FreeVisitPrice(), Pricing, rialToToman(), tomanToRial(), IbanItem, RepMe, RepresentationSettlementPage(), RepSummary (+12 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (45): FreeVisitPrice(), Pricing, cn(), formatDateTime(), formatRial(), iranMobileOptionalSchema, iranMobileSchema, isValidIranMobile() (+37 more)
|
||||
|
||||
### Community 64 - "Community 64"
|
||||
Cohesion: 0.29
|
||||
Nodes (4): SmsWalletController, JsonResponse, Request, User
|
||||
Cohesion: 0.19
|
||||
Nodes (7): SmsWalletController, SmsSettingsRepository, SmsSettings, JsonResponse, Request, User, ManagerRegistry
|
||||
|
||||
### Community 65 - "Community 65"
|
||||
Cohesion: 0.08
|
||||
@@ -1041,7 +1030,7 @@ Nodes (12): رفع بهمریختگی کامل پنل ادمین روی iPhon
|
||||
|
||||
### Community 71 - "Community 71"
|
||||
Cohesion: 0.09
|
||||
Nodes (21): AddForm, addSchema, ClinicsPage(), HUES_LIST, EMPTY, PreRegistration, STATUS_META, STATUS_TABS (+13 more)
|
||||
Nodes (19): AddForm, addSchema, ClinicsPage(), HUES_LIST, EMPTY, PreRegistration, STATUS_META, STATUS_TABS (+11 more)
|
||||
|
||||
### Community 72 - "Community 72"
|
||||
Cohesion: 0.09
|
||||
@@ -1075,6 +1064,10 @@ Nodes (3): SubscriptionPlan, Collection, self
|
||||
Cohesion: 0.09
|
||||
Nodes (23): dependencies, @ckeditor/ckeditor5-build-classic, @ckeditor/ckeditor5-react, @fontsource/vazirmatn, @heroicons/react, @hookform/resolvers, jalaali-js, leaflet (+15 more)
|
||||
|
||||
### Community 82 - "Community 82"
|
||||
Cohesion: 0.07
|
||||
Nodes (8): CategoryImportTest, Connection, RepositoryClassMappingTest, KernelTestCase, DbLogger, CategoryImporter, DbLoggerTest, Stringable
|
||||
|
||||
### Community 83 - "Community 83"
|
||||
Cohesion: 0.09
|
||||
Nodes (21): Backend, CSS / UI, Frontend, روند اجرای هر قابلیت, قبل از شروع — تحلیل پرامپت و ساخت Todo, قوانین اجرا (اجباری — هیچ استثنایی ندارد), قوانین خاص این پروژه, مثال اجرا (+13 more)
|
||||
@@ -1089,7 +1082,7 @@ Nodes (30): devDependencies, @babel/core, @babel/preset-env, @babel/preset-react
|
||||
|
||||
### Community 86 - "Community 86"
|
||||
Cohesion: 0.06
|
||||
Nodes (14): AppointmentExpiryServiceTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, ServiceItemStaffOwnershipTest, EntityManagerInterface, KernelBrowser, CommentPaginationTest (+6 more)
|
||||
Nodes (15): AppointmentExpiryServiceTest, DateOverrideOwnershipTest, LowTierFixesTest, SendCodeMobileRateLimitTest, ClaimsListPaginationTest, ServiceItemStaffOwnershipTest, EntityManagerInterface, KernelBrowser (+7 more)
|
||||
|
||||
### Community 87 - "Community 87"
|
||||
Cohesion: 0.10
|
||||
@@ -1160,8 +1153,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.18
|
||||
Nodes (6): TagController, TagRepository, JsonResponse, Request, ManagerRegistry, Tag
|
||||
Cohesion: 0.35
|
||||
Nodes (3): TagController, JsonResponse, Request
|
||||
|
||||
### Community 105 - "Community 105"
|
||||
Cohesion: 0.11
|
||||
@@ -1276,8 +1269,8 @@ Cohesion: 0.12
|
||||
Nodes (16): Endpoint ها, GET /api/v1/representation/filter/{id}, GET /api/v1/representation/filter/{representationId}, GET /api/v1/representation/my-appointments/{id}, GET /api/v1/representation/{uuid}, GET /api/v1/representation/yearly-income/{id}, GET /api/v1/representation/yearly-income/{representationId}, POST /api/v1/representations/{id}/bank-accounts (+8 more)
|
||||
|
||||
### Community 135 - "Community 135"
|
||||
Cohesion: 0.09
|
||||
Nodes (22): Appointment Settings API, Available Locations, Day Index Convention, DELETE `/api/v1/booking-setting/{uuid}`, Errors, Errors, Errors, Errors (+14 more)
|
||||
Cohesion: 0.12
|
||||
Nodes (16): Day Index Convention, DELETE `/api/v1/booking-setting/{uuid}`, Errors, Errors, Errors, Errors, GET `/api/v1/appointment-settings/weekly-schedule/{uuid}`, PATCH `/api/v1/appointment-settings/weekly-schedule/{uuid}` (+8 more)
|
||||
|
||||
### Community 136 - "Community 136"
|
||||
Cohesion: 0.12
|
||||
@@ -1384,8 +1377,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.11
|
||||
Nodes (18): autoload, autoload-dev, psr-4, psr-4, conflict, symfony/symfony, description, extra (+10 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (14): autoload, autoload-dev, psr-4, psr-4, conflict, symfony/symfony, description, license (+6 more)
|
||||
|
||||
### Community 164 - "Community 164"
|
||||
Cohesion: 0.29
|
||||
@@ -1408,8 +1401,8 @@ Cohesion: 0.10
|
||||
Nodes (20): api.ir (استعلام هویت — Shahkar / IbanMatch), اتصال به دیتابیسهای مستقل (الزامی), اسرار (الزامی — قبل از اولین دیپلوی), امنیت و منابع, بررسی سلامت, دامنهها و CORS, دیپلویهای بعدی, راهنمای دیپلوی ClinicPro (Coolify + Docker Compose) (+12 more)
|
||||
|
||||
### Community 169 - "Community 169"
|
||||
Cohesion: 0.15
|
||||
Nodes (5): EntityInsurancePricing, TenantInsuranceCleanupTest, EntityInsurancePricingRepository, TenantInsuranceCleanupService, ManagerRegistry
|
||||
Cohesion: 0.22
|
||||
Nodes (4): EntityInsurancePricing, TenantInsuranceCleanupTest, EntityInsurancePricingRepository, ManagerRegistry
|
||||
|
||||
### Community 170 - "Community 170"
|
||||
Cohesion: 0.13
|
||||
@@ -1459,6 +1452,10 @@ Nodes (3): PatientRecord, Collection, User
|
||||
Cohesion: 0.23
|
||||
Nodes (3): WeeklySchedule, Doctor, self
|
||||
|
||||
### Community 182 - "Community 182"
|
||||
Cohesion: 0.07
|
||||
Nodes (5): SmsSettings, SmsWallet, LogPruneService, AppointmentExpiryService, self
|
||||
|
||||
### Community 183 - "Community 183"
|
||||
Cohesion: 0.14
|
||||
Nodes (13): `UserDetailPage.tsx` — فقط user query, زمینه, فایلهای مرتبط, قرارداد پروفایل (`UserProfile.toArray`), مشکل / هدف, نمایش پروفایل کاربر در صفحهی جزئیات کاربرِ پنل ادمین, نکات مهم, وضعیت فعلی (کد واقعی) (+5 more)
|
||||
@@ -1528,8 +1525,8 @@ Cohesion: 0.14
|
||||
Nodes (13): Endpoint ها, PATCH /api/v1/secretary/{uuid}, POST /api/v1/secretary, تسک ۱۴: ماژول منشی, توضیح, زمان تخمینی, ساختار JSON, سیستم مجوزها — Resource-Based Permissions (مقیاسپذیر) (+5 more)
|
||||
|
||||
### Community 201 - "Community 201"
|
||||
Cohesion: 0.15
|
||||
Nodes (13): Admin API, Clinic Invitation Management, GET `/api/v1/admin/pre-registrations`, GET `/api/v1/admin/secretaries`, GET /api/v1/admin/settings, PATCH /api/v1/admin/settings, POST `/api/v1/admin/pre-registrations/{uuid}/approve`, POST `/api/v1/admin/pre-registrations/{uuid}/reject` (+5 more)
|
||||
Cohesion: 0.12
|
||||
Nodes (16): Admin API, Clinic Invitation Management, Dashboard, GET `/api/v1/admin/dashboard/charts`, GET `/api/v1/admin/dashboard/recent`, GET `/api/v1/admin/dashboard/stats`, GET `/api/v1/admin/pre-registrations`, GET /api/v1/admin/settings (+8 more)
|
||||
|
||||
### Community 202 - "Community 202"
|
||||
Cohesion: 0.15
|
||||
@@ -1608,8 +1605,8 @@ Cohesion: 0.23
|
||||
Nodes (5): PaymentRepository, Appointment, ManagerRegistry, Payment, User
|
||||
|
||||
### Community 225 - "Community 225"
|
||||
Cohesion: 0.05
|
||||
Nodes (37): formatDate(), formatDateTime(), ALL_STATUSES, AppointmentDetailPage(), timeOf(), Claim, ClaimItem, DebtRow (+29 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (18): formatDate(), toDate(), ALL_STATUSES, AppointmentDetailPage(), timeOf(), Claim, ClaimItem, DebtRow (+10 more)
|
||||
|
||||
### Community 226 - "Community 226"
|
||||
Cohesion: 0.15
|
||||
@@ -1620,8 +1617,8 @@ Cohesion: 0.17
|
||||
Nodes (11): تشخیص عمیق down شدن سرور بعد از ~۱۰ سیکل + وریفای و تکمیل فیکسهای پایداری, زمینه, فایلهای مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی, وظایف, ۱. وریفای فیکسهای repo (idempotent) (+3 more)
|
||||
|
||||
### Community 228 - "Community 228"
|
||||
Cohesion: 0.20
|
||||
Nodes (10): Bulk import / export, DELETE `/api/v1/admin/insurance/{id}`, DELETE `/api/v1/insurance/{id}`, EntityInsurancePricing — قیمتگذاری ویزیت بر اساس بیمه, GET `/api/v1/insurance/{id}`, Insurance API, Response `200`, Response `200` (+2 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (47): 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 (+39 more)
|
||||
|
||||
### Community 229 - "Community 229"
|
||||
Cohesion: 0.14
|
||||
@@ -1760,8 +1757,8 @@ Cohesion: 0.30
|
||||
Nodes (4): RepresentationRepository, ManagerRegistry, Representation, User
|
||||
|
||||
### Community 265 - "Community 265"
|
||||
Cohesion: 0.06
|
||||
Nodes (33): Contract, InsuranceOption, KIND_LABEL, calcFinalPrice(), EMPTY_RECORDS, EMPTY_SESSIONS, fileNumber(), getPatientName() (+25 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (27): calcFinalPrice(), EMPTY_RECORDS, EMPTY_SESSIONS, fileNumber(), getPatientName(), getPatientPhone(), InsurancePricing, MyPatientsPageInner() (+19 more)
|
||||
|
||||
### Community 266 - "Community 266"
|
||||
Cohesion: 0.33
|
||||
@@ -1796,7 +1793,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.21
|
||||
Cohesion: 0.20
|
||||
Nodes (5): Authentication, ClinicPro — API Documentation Index, Error Code Reference, Modules, Standard Response Envelope
|
||||
|
||||
### Community 275 - "Community 275"
|
||||
@@ -1900,8 +1897,8 @@ Cohesion: 0.42
|
||||
Nodes (3): PreRegistrationController, JsonResponse, Request
|
||||
|
||||
### Community 301 - "Community 301"
|
||||
Cohesion: 0.06
|
||||
Nodes (31): cn(), iranMobileOptionalSchema, iranMobileSchema, isValidIranMobile(), maskMobile(), sanitizeMobileInput(), toDate(), toEnglishDigits() (+23 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (18): ClinicAddress, ClinicDoctorItem, ClinicInvitation, EditForm, editSchema, HUES_LIST, INV_STATUS_MAP, IRAN_CENTER (+10 more)
|
||||
|
||||
### Community 302 - "Community 302"
|
||||
Cohesion: 0.12
|
||||
@@ -1912,8 +1909,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 🆕, 33. 🔵 `POST` image_clinic, 6. کلینیک (Clinic), هدرهای اضافی, پارامترهای Query, پاسخها, پاسخها (+1 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (47): 29. 🟢 `GET` clinic list 🆕, 30. 🟢 `GET` get 🆕, 33. 🔵 `POST` image_clinic, 34. 🔵 `POST` image logo, 36. 🟢 `GET` get my rate, 37. 🔵 `POST` post, 38. 🟢 `GET` Unapproved comments, 39. 🟡 `PATCH` Comment confirmation (+39 more)
|
||||
|
||||
### Community 306 - "Community 306"
|
||||
Cohesion: 0.07
|
||||
@@ -2012,8 +2009,8 @@ Cohesion: 0.22
|
||||
Nodes (8): Query های جدید, بیماران منحصربهفرد در بازه, درآمد بر اساس روز (از patient_sessions), فروش اشتراک بر اساس پنل (admin), نوبتها بر اساس روز (admin chart), نکات مهم, هیچ migration لازم نیست, پایگاه داده — تسک ۱۶: داشبورد هوشمند
|
||||
|
||||
### Community 333 - "Community 333"
|
||||
Cohesion: 0.05
|
||||
Nodes (40): DELETE `/api/v1/clinic-pro/doctor-address/{id}`, Doctor API, Errors, Errors, Errors, Errors, Errors, Errors (+32 more)
|
||||
Cohesion: 0.25
|
||||
Nodes (7): DELETE `/api/v1/clinic-pro/doctor-address/{id}`, Doctor API, Errors, GET `/api/v1/doctors`, Query Parameters, Response `200`, Response `200`
|
||||
|
||||
### Community 334 - "Community 334"
|
||||
Cohesion: 0.25
|
||||
@@ -2140,8 +2137,8 @@ Cohesion: 0.25
|
||||
Nodes (7): ادمین, دکتر نمونه کامل — تبریز, دکتران bulk (۱۵۰۰ دکتر در ۱۵ شهر), ساخت مجدد, منشی دکتر نمونه, کاربران تستی, کلینیک نمونه — تبریز
|
||||
|
||||
### Community 367 - "Community 367"
|
||||
Cohesion: 0.29
|
||||
Nodes (7): Dashboard, GET `/api/v1/admin/dashboard/charts`, GET `/api/v1/admin/dashboard/recent`, GET `/api/v1/admin/dashboard/stats`, Response `200`, Response `200`, Response `200`
|
||||
Cohesion: 0.13
|
||||
Nodes (12): AdminUserDetail, AVATAR_COLORS, EditForm, editSchema, GENDER_LABELS, getPrimaryRole(), MARITAL_LABELS, MEDICAL_SECTIONS (+4 more)
|
||||
|
||||
### Community 368 - "Community 368"
|
||||
Cohesion: 0.36
|
||||
@@ -2261,7 +2258,7 @@ Nodes (7): initiate(), refund(), reverse(), verify(), PaymentInitResult, Payment
|
||||
|
||||
### Community 399 - "Community 399"
|
||||
Cohesion: 0.23
|
||||
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260628165710
|
||||
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260611075829
|
||||
|
||||
### Community 401 - "Community 401"
|
||||
Cohesion: 0.12
|
||||
@@ -2272,7 +2269,7 @@ Cohesion: 0.11
|
||||
Nodes (17): بازطراحی معماری پرداخت — سرویسمحور، امن، توسعهپذیر (Backend), تست دستی (ddev، در حالت `payment_test_mode=1`), خروجی نهایی (طبق spec — در گزارش اجرا ارائه شود), زمینه, فایلهای مرتبط, مشکل / هدف, نکات مهم, وضعیت فعلی (+9 more)
|
||||
|
||||
### Community 407 - "Community 407"
|
||||
Cohesion: 0.16
|
||||
Cohesion: 0.15
|
||||
Nodes (11): MessageBusInterface, MockObject, SmsService, SmsServiceLookupOnlyTest, SmsLogRepository, SmsMessageTemplateRepository, SmsService, SmsTextResolver (+3 more)
|
||||
|
||||
### Community 418 - "Community 418"
|
||||
@@ -2296,12 +2293,12 @@ Cohesion: 0.35
|
||||
Nodes (5): PatientController, JsonResponse, PatientSession, Request, User
|
||||
|
||||
### Community 435 - "Community 435"
|
||||
Cohesion: 0.33
|
||||
Nodes (4): BlogController, JsonResponse, Request, User
|
||||
Cohesion: 0.43
|
||||
Nodes (3): InvoiceRepository, Invoice, ManagerRegistry
|
||||
|
||||
### Community 439 - "Community 439"
|
||||
Cohesion: 0.43
|
||||
Nodes (3): InvoiceItemRepository, InvoiceItem, ManagerRegistry
|
||||
Cohesion: 0.39
|
||||
Nodes (3): TagRepository, ManagerRegistry, Tag
|
||||
|
||||
### Community 440 - "Community 440"
|
||||
Cohesion: 0.11
|
||||
@@ -2407,6 +2404,14 @@ Nodes (3): TaxRateHistoryRepository, ManagerRegistry, TaxRateHistory
|
||||
Cohesion: 0.47
|
||||
Nodes (3): CommissionService, Payment, Representation
|
||||
|
||||
### Community 483 - "Community 483"
|
||||
Cohesion: 0.29
|
||||
Nodes (6): Appointment Settings API, Available Locations, Errors, `GET /api/v1/appointment-settings/available-locations/{doctorUuid}`, Response `200`, Slot Calculation Logic (Reference)
|
||||
|
||||
### Community 485 - "Community 485"
|
||||
Cohesion: 0.43
|
||||
Nodes (3): SmsMessageController, JsonResponse, Request
|
||||
|
||||
### Community 486 - "Community 486"
|
||||
Cohesion: 0.40
|
||||
Nodes (5): ۲.۸ تنظیمات نوبت (Appointment Settings), ۲.۸.۱ برنامه هفتگی (Weekly Schedule), ۲.۸.۲ تعطیلات (Holidays), ۲.۸.۳ لغو تعطیل (Date Override), ۲.۸.۴ الگوریتم محاسبه اسلاتهای خالی
|
||||
@@ -2420,8 +2425,8 @@ 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 490 - "Community 490"
|
||||
Cohesion: 0.15
|
||||
Nodes (11): emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema, PLAN_DISPLAY, PlanForm, planSchema (+3 more)
|
||||
Cohesion: 0.06
|
||||
Nodes (29): PaymentConfig, PaymentGatewayInfo, usePaymentConfig(), emptyFeatures(), FEATURE_KEYS, FEATURE_LABELS, PeriodForm, periodSchema (+21 more)
|
||||
|
||||
### Community 491 - "Community 491"
|
||||
Cohesion: 0.12
|
||||
@@ -2592,8 +2597,8 @@ Cohesion: 0.22
|
||||
Nodes (3): AppException, SlotTakenException, RuntimeException
|
||||
|
||||
### Community 542 - "Community 542"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 38. 🟢 `GET` Unapproved comments, هدرهای اضافی, پارامترهای Query, پاسخها
|
||||
Cohesion: 0.48
|
||||
Nodes (3): DoctorInsuranceRepository, DoctorInsurance, ManagerRegistry
|
||||
|
||||
### Community 543 - "Community 543"
|
||||
Cohesion: 0.30
|
||||
@@ -2660,8 +2665,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
|
||||
@@ -2747,10 +2752,6 @@ Nodes (3): Entity: Payment, ساختار فایلها, معماری — تس
|
||||
Cohesion: 0.40
|
||||
Nodes (5): Errors, GET `/api/v1/clinic/my-doctor/{doctorUuid}`, Path Parameters, Response `200`, Schedule Fields Notes
|
||||
|
||||
### Community 596 - "Community 596"
|
||||
Cohesion: 0.38
|
||||
Nodes (3): RepositoryClassMappingTest, KernelTestCase, DbLoggerTest
|
||||
|
||||
### Community 597 - "Community 597"
|
||||
Cohesion: 0.29
|
||||
Nodes (7): Configuration, Errors, GET `/api/v1/admin/sms/templates`, GET `/api/v1/sms/template/{uuid}`, Response `200`, Response `200`, SMS API
|
||||
@@ -2775,10 +2776,6 @@ Nodes (3): ماژولهای شناساییشده در PRD, موارد پو
|
||||
Cohesion: 0.67
|
||||
Nodes (3): نقاط ضعف, نقاط قوت, ۶. تحلیل API Design
|
||||
|
||||
### Community 606 - "Community 606"
|
||||
Cohesion: 0.15
|
||||
Nodes (3): LoggerInterface, RanginehProvider, ApiIrService
|
||||
|
||||
### Community 607 - "Community 607"
|
||||
Cohesion: 0.34
|
||||
Nodes (5): RepresentationController, JsonResponse, Representation, Request, User
|
||||
@@ -2788,8 +2785,8 @@ Cohesion: 0.67
|
||||
Nodes (3): بکاند, فرانتاند, وضعیت فعلی کد (مهم — قبل از تغییر بخوان)
|
||||
|
||||
### Community 618 - "Community 618"
|
||||
Cohesion: 0.16
|
||||
Nodes (5): ServiceItemDeleteCleanupTest, ServiceCoverageNPlusOneTest, TenantServiceCoverageRepository, ManagerRegistry, TenantServiceCoverage
|
||||
Cohesion: 0.12
|
||||
Nodes (6): ServiceItemDeleteCleanupTest, ServiceCoverageNPlusOneTest, TenantServiceCoverageRepository, TenantInsuranceCleanupService, ManagerRegistry, TenantServiceCoverage
|
||||
|
||||
### Community 631 - "Community 631"
|
||||
Cohesion: 0.50
|
||||
@@ -2799,10 +2796,6 @@ Nodes (4): GET `/api/v1/admin/representations`, Query Parameters, Representation
|
||||
Cohesion: 0.50
|
||||
Nodes (4): DELETE `/api/v1/doctor/{uuid}`, Errors, Path Parameters, Response `200`
|
||||
|
||||
### Community 633 - "Community 633"
|
||||
Cohesion: 0.48
|
||||
Nodes (3): SmsSettingsRepository, SmsSettings, ManagerRegistry
|
||||
|
||||
### Community 634 - "Community 634"
|
||||
Cohesion: 0.47
|
||||
Nodes (3): ImageCropModalProps, createImage(), getCroppedImage()
|
||||
@@ -2812,8 +2805,8 @@ Cohesion: 0.12
|
||||
Nodes (16): Runbook — تشخیص «ریاستارت» سرور: recycle عادی یا خرابی واقعی؟, اقدامات تکمیلی روی سرور (خارج از repo), تأیید روی سرور — اسکریپت آماده, جدول تفسیر خروجی اسکریپت, خلاصه یکخطی, علامت مشکل, چرا این اتفاق میافتاد (و فیکس اعمالشده), چکلیست رفع (+8 more)
|
||||
|
||||
### Community 638 - "Community 638"
|
||||
Cohesion: 0.53
|
||||
Nodes (3): SessionServiceRepository, ManagerRegistry, SessionService
|
||||
Cohesion: 0.40
|
||||
Nodes (5): Errors, PATCH `/api/v1/doctor/{uuid}`, Path Parameters, Request Body (`application/json`), Response `200`
|
||||
|
||||
### Community 640 - "Community 640"
|
||||
Cohesion: 0.40
|
||||
@@ -2872,12 +2865,12 @@ Cohesion: 0.43
|
||||
Nodes (3): SmsLogRepository, SmsLog, ManagerRegistry
|
||||
|
||||
### Community 662 - "Community 662"
|
||||
Cohesion: 0.29
|
||||
Nodes (7): Application Logs, DELETE `/api/v1/admin/logs`, GET `/api/v1/admin/logs`, Log Retention, Query Parameters, Response `200`, Response `200`
|
||||
Cohesion: 0.20
|
||||
Nodes (10): Application Logs, DELETE `/api/v1/admin/logs`, GET `/api/v1/admin/logs`, GET `/api/v1/admin/logs/export`, Log Retention, Query Parameters, Query Parameters, Response `200` (+2 more)
|
||||
|
||||
### Community 667 - "Community 667"
|
||||
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 (فاز ۱ سیستم صورتحساب)
|
||||
Nodes (5): Errors, PATCH `/api/v1/clinic-pro/doctor-address/{id}`, Path Parameters, Request Body, Response `200`
|
||||
|
||||
### Community 672 - "Community 672"
|
||||
Cohesion: 0.17
|
||||
@@ -2888,20 +2881,20 @@ Cohesion: 0.50
|
||||
Nodes (4): Errors, POST `/api/v1/user/register`, Request Body, Response `201`
|
||||
|
||||
### Community 674 - "Community 674"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, GET `/api/v1/admin/insurances`, Query Parameters, Response `200`
|
||||
Cohesion: 0.40
|
||||
Nodes (3): Props, StatTone, TONE
|
||||
|
||||
### Community 675 - "Community 675"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, POST `/api/v1/admin/insurance`, Request Body (`application/json`), Response `201`
|
||||
Nodes (4): GET `/api/v1/admin/secretaries`, Query Parameters, Response `200`, Secretary Management
|
||||
|
||||
### Community 676 - "Community 676"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, POST `/api/v1/insurance/`, Request Body (`application/json`), Response `201`
|
||||
Nodes (4): Errors, POST `/api/v1/doctor`, Request Body (`application/json`), Response `201`
|
||||
|
||||
### Community 677 - "Community 677"
|
||||
Cohesion: 0.43
|
||||
Nodes (5): BeforeInstallPromptEvent, usePwaInstall(), PwaInstallBanner(), detectIOS(), PwaLoginCard()
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, GET `/api/v1/doctor/{uuid}`, Path Parameters, Response `200`
|
||||
|
||||
### Community 678 - "Community 678"
|
||||
Cohesion: 0.50
|
||||
@@ -2913,7 +2906,7 @@ Nodes (4): Errors, POST `/api/v1/auth/switch-context`, Request Body, Response `2
|
||||
|
||||
### Community 684 - "Community 684"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, PATCH `/api/v1/insurance/{id}`, Request Body, Response `200`
|
||||
Nodes (4): Errors, POST `/file/upload/clinic_pro/doctor/field_image`, Request, Response `200`
|
||||
|
||||
### Community 686 - "Community 686"
|
||||
Cohesion: 0.40
|
||||
@@ -2925,23 +2918,19 @@ Nodes (4): Errors, PATCH `/api/v1/admin/insurance/{id}`, Path Parameters, Respon
|
||||
|
||||
### Community 689 - "Community 689"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): PUT `/api/v1/insurance-pricing`, Request Body, Response `200`, خطاها
|
||||
Nodes (4): Errors, POST `/api/v1/clinic-pro/doctor-address`, Request Body, Response `201`
|
||||
|
||||
### Community 690 - "Community 690"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): GET `/api/v1/billing/tenant-insurances/{uuid}/service-coverage`, PUT `/api/v1/billing/tenant-insurances/{uuid}/service-coverage`, TenantServiceCoverage — پوشش خدمت تحت یک قرارداد بیمه (فاز ۲)
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, Path Parameters, POST `/api/v1/clinic-pro/doctor-address/from-clinic/{clinicUuid}`, Response `201`
|
||||
|
||||
### Community 692 - "Community 692"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): GET `/api/v1/insurance-pricing`, Response `200`, خطاها
|
||||
Cohesion: 0.50
|
||||
Nodes (4): extra, symfony, allow-contrib, require
|
||||
|
||||
### Community 693 - "Community 693"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): GET `/api/v1/insurances`, Query Parameters, Response `200`
|
||||
|
||||
### Community 694 - "Community 694"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): POST `/api/v1/admin/insurance/{id}/upload-logo`, Request, Response `200`
|
||||
Nodes (3): GET `/api/v1/clinic-pro/doctor-addresses/{doctorId}`, Path Parameters, Response `200`
|
||||
|
||||
### Community 695 - "Community 695"
|
||||
Cohesion: 0.67
|
||||
@@ -2963,26 +2952,14 @@ Nodes (11): رفع خطای `Class "SoapClient" not found` در پرداخت م
|
||||
Cohesion: 0.40
|
||||
Nodes (5): 32. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 705 - "Community 705"
|
||||
Cohesion: 0.40
|
||||
Nodes (5): 37. 🔵 `POST` post, Request Body, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 706 - "Community 706"
|
||||
Cohesion: 0.53
|
||||
Nodes (3): PaymentLog, PaymentLogRepository, ManagerRegistry
|
||||
|
||||
### Community 707 - "Community 707"
|
||||
Cohesion: 0.38
|
||||
Nodes (5): Rate, RateRepository, Doctor, ManagerRegistry, User
|
||||
|
||||
### Community 708 - "Community 708"
|
||||
Cohesion: 0.33
|
||||
Nodes (4): PatientService, Appointment, PatientRecord, PatientSession
|
||||
|
||||
### Community 710 - "Community 710"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 39. 🟡 `PATCH` Comment confirmation, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 712 - "Community 712"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 44. 🟢 `GET` list comment, هدرهای اضافی, پارامترهای Query, پاسخها
|
||||
@@ -2995,22 +2972,10 @@ Nodes (5): 31. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای
|
||||
Cohesion: 0.40
|
||||
Nodes (5): 35. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 716 - "Community 716"
|
||||
Cohesion: 0.40
|
||||
Nodes (5): 41. 🟡 `PATCH` patch, Request Body, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 720 - "Community 720"
|
||||
Cohesion: 0.33
|
||||
Nodes (3): Closure, CorsRegexEnvProcessor, EnvVarProcessorInterface
|
||||
|
||||
### Community 723 - "Community 723"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 40. 🔵 `POST` post, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 724 - "Community 724"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): 45. 🔵 `POST` post, مثال Request, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 725 - "Community 725"
|
||||
Cohesion: 0.43
|
||||
Nodes (3): InvoiceService, Invoice, PatientSession
|
||||
@@ -3031,44 +2996,28 @@ Nodes (3): Errors, GET `/api/v1/notification-mobile/{target}`, Response `200`
|
||||
Cohesion: 0.67
|
||||
Nodes (3): GET `/api/v1/representation/{uuid}/dashboard/yearly`, Query Parameters, Response `200`
|
||||
|
||||
### Community 732 - "Community 732"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 36. 🟢 `GET` get my rate, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 733 - "Community 733"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 34. 🔵 `POST` image logo, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 734 - "Community 734"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 42. 🔴 `DELETE` delete, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 735 - "Community 735"
|
||||
Cohesion: 0.67
|
||||
Nodes (3): 43. 🟢 `GET` get, هدرهای اضافی, پاسخها
|
||||
|
||||
### Community 738 - "Community 738"
|
||||
Cohesion: 0.50
|
||||
Nodes (4): Errors, GET `/api/v1/representation/{uuid}`, Path Parameters, Response `200`
|
||||
|
||||
## Knowledge Gaps
|
||||
- **4007 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps`, `TenantInsurance`, `CoverageRow` (+4002 more)
|
||||
- **4009 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps`, `TenantInsurance`, `CoverageRow` (+4004 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **151 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||
- **145 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 654`, `Community 655`, `Community 15`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 295`, `Community 424`, `Community 300`, `Community 559`, `Community 433`, `Community 435`, `Community 308`, `Community 59`, `Community 318`, `Community 64`, `Community 75`, `Community 77`, `Community 607`, `Community 480`, `Community 230`, `Community 104`, `Community 107`, `Community 109`, `Community 245`, `Community 380`, `Community 121`, `Community 122`, `Community 252`?**
|
||||
_High betweenness centrality (0.035) - this node is a cross-community bridge._
|
||||
- **Why does `ApiTestCase` connect `Community 86` to `Community 397`, `Community 534`, `Community 535`, `Community 541`, `Community 41`, `Community 169`, `Community 562`, `Community 565`, `Community 573`, `Community 574`, `Community 575`, `Community 717`, `Community 718`, `Community 594`, `Community 82`, `Community 609`, `Community 484`, `Community 618`, `Community 497`, `Community 371`?**
|
||||
_High betweenness centrality (0.022) - this node is a cross-community bridge._
|
||||
- **Why does `BaseController` connect `Community 108` to `Community 6`, `Community 138`, `Community 139`, `Community 14`, `Community 654`, `Community 655`, `Community 15`, `Community 20`, `Community 22`, `Community 26`, `Community 164`, `Community 295`, `Community 424`, `Community 300`, `Community 433`, `Community 308`, `Community 58`, `Community 59`, `Community 318`, `Community 64`, `Community 75`, `Community 77`, `Community 607`, `Community 480`, `Community 485`, `Community 230`, `Community 104`, `Community 107`, `Community 109`, `Community 245`, `Community 380`, `Community 121`, `Community 122`, `Community 252`?**
|
||||
_High betweenness centrality (0.026) - this node is a cross-community bridge._
|
||||
- **Why does `Version20260705070546` connect `Community 646` to `Community 399`?**
|
||||
_High betweenness centrality (0.019) - this node is a cross-community bridge._
|
||||
- **Why does `ApiTestCase` connect `Community 86` to `Community 397`, `Community 22`, `Community 535`, `Community 534`, `Community 541`, `Community 169`, `Community 562`, `Community 565`, `Community 573`, `Community 574`, `Community 575`, `Community 594`, `Community 82`, `Community 609`, `Community 484`, `Community 618`, `Community 497`, `Community 371`, `Community 633`?**
|
||||
_High betweenness centrality (0.018) - this node is a cross-community bridge._
|
||||
- **What connects `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps` to the rest of the system?**
|
||||
_4007 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
_4009 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||
- **Should `Community 0` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.05200501253132832 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.05004389815627744 - 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?**
|
||||
|
||||
graphify-out/cache/ast/v0.8.44/40f30916ed90294b3c7d20df1c26523ab8a0bc38789dd43e974aa44c45070308.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/a9f43467a79de3366505fa643850b2cbd96e37bb265b652720f1a2b30340a317.json
Vendored
+1
File diff suppressed because one or more lines are too long
graphify-out/cache/ast/v0.8.44/c7f6f6958ff7097db77960d3d29e72ba9563bcf13fad264ccbd8af92b989dc5d.json
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+805
-578
File diff suppressed because it is too large
Load Diff
+12
-12
@@ -155,8 +155,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"assets/admin/lib/api.ts": {
|
||||
"mtime": 1782396341.3121104,
|
||||
"ast_hash": "0c8c5044646343d9901c96c7ae4175b5",
|
||||
"mtime": 1783663912.9593666,
|
||||
"ast_hash": "e9eb6990a4e8b4467907f5df6fa87ef9",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"assets/admin/lib/utils.ts": {
|
||||
@@ -810,8 +810,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/Admin/Controller/AdminApiController.php": {
|
||||
"mtime": 1783569345.7785833,
|
||||
"ast_hash": "76990cb279d535ab2d869f87752a185a",
|
||||
"mtime": 1783663902.0176175,
|
||||
"ast_hash": "1be6bc6af210c01303d49cf031d05593",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/Admin/Controller/AdminController.php": {
|
||||
@@ -2340,8 +2340,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"docs/api/admin.md": {
|
||||
"mtime": 1783569345.7769597,
|
||||
"ast_hash": "c0e70f627d969f3449dbe58fe653a9bf",
|
||||
"mtime": 1783663961.4046154,
|
||||
"ast_hash": "0ecb4de166b81cb69125d9c6b59f8d16",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"docs/api/appointment-settings.md": {
|
||||
@@ -3245,8 +3245,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"docker-compose.yml": {
|
||||
"mtime": 1783520508.741232,
|
||||
"ast_hash": "75c5d64fa9241dd92c5a0b9999f8241f",
|
||||
"mtime": 1783608242.4596496,
|
||||
"ast_hash": "466eb229daac6f54667dd7ecb20efadf",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"docs/DEPLOY.md": {
|
||||
@@ -3375,8 +3375,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"assets/admin/pages/LogsPage.tsx": {
|
||||
"mtime": 1782929861.6704445,
|
||||
"ast_hash": "2e9aed8e9f683011985c6c932644892a",
|
||||
"mtime": 1783663932.1559613,
|
||||
"ast_hash": "c2b170578a588a65b894a7c5e2da2de5",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"migrations/Version20260629161536.php": {
|
||||
@@ -3400,8 +3400,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"tests/Admin/AdminLogsTest.php": {
|
||||
"mtime": 1782750195.979033,
|
||||
"ast_hash": "6622637d75fe6e5fc81b9c9236f03191",
|
||||
"mtime": 1783664104.075507,
|
||||
"ast_hash": "738f8fd28b22ea6d6a9ed31d91c27b6b",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"tests/Shared/DbLoggerTest.php": {
|
||||
|
||||
@@ -26,6 +26,7 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -2098,6 +2099,72 @@ class AdminApiController extends BaseController
|
||||
], $rows), (int) $total, $page, $limit);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/admin/logs/export',
|
||||
summary: 'Export all persisted application logs as CSV (respects filters, no pagination)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'level', in: 'query', required: false, description: 'PSR level filter (warning/error/critical/...)', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, description: 'substring match on message', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'from', in: 'query', required: false, description: 'unix timestamp lower bound', schema: new OA\Schema(type: 'integer')),
|
||||
new OA\Parameter(name: 'to', in: 'query', required: false, description: 'unix timestamp upper bound', schema: new OA\Schema(type: 'integer')),
|
||||
],
|
||||
responses: [new OA\Response(response: 200, description: 'CSV file (text/csv) of all matching logs')]
|
||||
)]
|
||||
#[Route('/api/v1/admin/logs/export', methods: ['GET'])]
|
||||
public function exportLogs(Request $request): StreamedResponse
|
||||
{
|
||||
$level = trim((string) $request->query->get('level', ''));
|
||||
$search = trim((string) $request->query->get('search', ''));
|
||||
$from = trim((string) $request->query->get('from', ''));
|
||||
$to = trim((string) $request->query->get('to', ''));
|
||||
|
||||
$qb = $this->em->createQueryBuilder()
|
||||
->select('l.id, l.level, l.message, l.context, l.channel, l.path, l.createdAt')
|
||||
->from(AppLog::class, 'l');
|
||||
|
||||
if ($level !== '') {
|
||||
$qb->andWhere('l.level = :level')->setParameter('level', $level);
|
||||
}
|
||||
if ($search !== '') {
|
||||
$qb->andWhere('l.message LIKE :s')->setParameter('s', '%' . $search . '%');
|
||||
}
|
||||
if ($from !== '') {
|
||||
$qb->andWhere('l.createdAt >= :from')->setParameter('from', (int) $from);
|
||||
}
|
||||
if ($to !== '') {
|
||||
$qb->andWhere('l.createdAt <= :to')->setParameter('to', (int) $to);
|
||||
}
|
||||
|
||||
$qb->orderBy('l.id', 'DESC');
|
||||
|
||||
$response = new StreamedResponse(function () use ($qb) {
|
||||
$out = fopen('php://output', 'w');
|
||||
// UTF-8 BOM so Excel renders Persian correctly
|
||||
fwrite($out, "\xEF\xBB\xBF");
|
||||
fputcsv($out, ['id', 'level', 'message', 'context', 'channel', 'path', 'created_at']);
|
||||
|
||||
foreach ($qb->getQuery()->toIterable([], \Doctrine\ORM\Query::HYDRATE_ARRAY) as $l) {
|
||||
fputcsv($out, [
|
||||
(int) $l['id'],
|
||||
$l['level'],
|
||||
$l['message'],
|
||||
$l['context'],
|
||||
$l['channel'],
|
||||
$l['path'],
|
||||
date('Y-m-d H:i:s', (int) $l['createdAt']),
|
||||
]);
|
||||
}
|
||||
fclose($out);
|
||||
});
|
||||
|
||||
$filename = 'logs-' . date('Ymd-His') . '.csv';
|
||||
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
|
||||
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
#[Route('/api/v1/admin/logs', methods: ['DELETE'])]
|
||||
public function clearLogs(): JsonResponse
|
||||
{
|
||||
|
||||
@@ -45,4 +45,39 @@ class AdminLogsTest extends ApiTestCase
|
||||
|
||||
$this->em->getConnection()->executeStatement('DELETE FROM app_log WHERE message LIKE ?', [$marker . '%']);
|
||||
}
|
||||
|
||||
public function testExportNonAdminForbidden(): void
|
||||
{
|
||||
$user = $this->createUser(['ROLE_USER']);
|
||||
$this->authJson('GET', '/api/v1/admin/logs/export', $user);
|
||||
self::assertSame(403, $this->responseCode());
|
||||
}
|
||||
|
||||
public function testAdminExportsCsvFilteredByLevel(): void
|
||||
{
|
||||
$marker = 'ADMINLOGEXPORT_' . bin2hex(random_bytes(5));
|
||||
$this->seedLog('error', $marker . '_err');
|
||||
$this->seedLog('warning', $marker . '_warn');
|
||||
|
||||
$admin = $this->createUser(['ROLE_ADMIN']);
|
||||
$this->client->request(
|
||||
'GET',
|
||||
'/api/v1/admin/logs/export?level=error&search=' . $marker,
|
||||
server: ['HTTP_AUTHORIZATION' => 'Bearer ' . $this->jwtFor($admin)],
|
||||
);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
self::assertSame(200, $response->getStatusCode());
|
||||
self::assertStringContainsString('text/csv', (string) $response->headers->get('Content-Type'));
|
||||
self::assertStringContainsString('attachment', (string) $response->headers->get('Content-Disposition'));
|
||||
|
||||
// StreamedResponse body is captured by BrowserKit into the internal response.
|
||||
$csv = $this->client->getInternalResponse()->getContent();
|
||||
|
||||
self::assertStringContainsString('id,level,message', $csv);
|
||||
self::assertStringContainsString($marker . '_err', $csv);
|
||||
self::assertStringNotContainsString($marker . '_warn', $csv);
|
||||
|
||||
$this->em->getConnection()->executeStatement('DELETE FROM app_log WHERE message LIKE ?', [$marker . '%']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user