#P1478
برگهٔ تازه
Route Info
| Method |
Endpoint |
Controller |
Middleware |
Purpose |
| GET |
/api/v2/settings/index/{type} |
V2BaseController@indexSettings |
authWithJwt |
دریافت تنظیمات و پیکربندیهای دفترکار براساس نوع درخواست (application، office، accounting، hub) |
منطق عملکرد تابع
تابع
indexSettings بر اساس پارامتر
{type} نوع پیکربندی را تشخیص میدهد و دادههای مربوط به هر بخش را از پایگاه داده میخواند. این تابع از یک switch-case یا نگاشت (Map) داخلی برای هدایت درخواست به منبع داده مناسب استفاده میکند. پارامتر
branch که از درخواست (معمولاً از توکن JWT استخراج میشود یا در پارامترهای کوئری موجود است) دریافت میگردد، به عنوان کلید اصلی برای فیلتر کردن تنظیمات مربوط به آن شعبه خاص عمل میکند.
- در حالت
application، جزئیات رابطهای برنامه و مشخصات گرافیکی سیستم (مانند لوگوها، رنگبندیهای پیشفرض، تنظیمات UI/UX عمومی) برمیگردد. این دادهها معمولاً کمتر تغییر میکنند و میتوانند کش شوند.
- در حالت
office، دادههای مربوط به نمایندگی فعلی (آدرس، وضعیت فعال/غیرفعال بودن، تنظیمات سرویسهای فعال، شمارههای تماس پشتیبانی) واکشی میشود. این تنظیمات مختص به نهاد شعبه جاری است.
- در حالت
accounting، اطلاعات مالی شاخه شامل base_online (حداقل اعتبار لازم برای رزروهای مستقیم آنلاین)، credit_limit (حداکثر اعتبار مجاز دفتر)، و عناوین حسابداری (مانند کدهای استاندارد خدمات، سرفصلهای مالی مورد استفاده در گزارشگیری) بازگردانده میشود.
- در حالت
hub، دادههای مربوط به تنظیمات markup برای انواع سرویسها (system، charter، airplus، accommodation و other) نمایش داده میشود. این تنظیمات اغلب شامل ضرایب افزایش قیمت یا تخفیفهای ثابت سیستمی هستند. محاسبه markup معمولاً بر اساس فرمول زیر است: [ \text{Price}{\text{Final}} = \text{Price}{\text{Base}} \times (1 + \text{MarkupPercentage}) + \text{FixedFee} ]
- خروجی بهصورت JSON شامل بخشهای تفکیکشده (مانند
application_config، office_data، financial، markup_rates) و زمان تولید پاسخ در متادیتا (meta.timestamp) است.
ورودیها (Request Fields)
| نام فیلد |
نوع داده |
الزامی |
توضیح |
| branch |
integer |
بله |
شناسه شعبه درخواستدهنده جهت واکشی داده تنظیمات. این شناسه معمولاً از JWT استخراج شده و در صورت عدم وجود، خطا برمیگرداند. |
| type |
string (enum) |
بله |
نوع تنظیمات مورد درخواست (application, office, accounting, hub). این پارامتر مسیر اصلی پردازش در کنترلر است. |
نمونه درخواست:
GET /api/v2/settings/index/accounting?branch=101
Host: api.example.com
Authorization: Bearer {JWT_TOKEN}
توجه: در این مثال، branch به عنوان کوئری پارامتر ارسال شده است، اما ممکن است از مسیر (Path Parameter) یا توکن JWT نیز استخراج شود.
خروجی (Response)
| فیلد |
نوع داده |
توضیح |
| status |
boolean |
وضعیت موفقیت عملیات (true در صورت موفقیت). |
| meta.timestamp |
integer |
زمان یونیکس پاسخ (Timestamp) جهت بررسی تازگی داده. |
| details |
object |
دادههای پیکربندی بسته به نوع درخواست (محتوای این شیء متغیر است). |
| financial.base_online |
float |
اعتبار پایه دفتر برای رزرو آنلاین (حداقل شارژ). |
| financial.credit_limit |
float |
سقف اعتبار کلی دفتر یا کاربری. |
| application.ui_theme |
string |
تم رابط کاربری انتخاب شده. |
نمونه پاسخ (نوع accounting):
{
"status": true,
"meta": { "timestamp": 1750669801, "path": "/api/v2/settings/index/accounting" },
"footer_announcements": "Accounting Tips: All payments must be settled within 48 hours.",
"financial": {
"base_online": 2000000.00,
"credit_limit": 10000000.00,
"currency": "IRR",
"bank": {
"name": "Mellat",
"iban": "IR12345678901234567890",
"account_number": "1234567"
}
},
"system_defaults": {
"default_tax_rate": 0.09
}
}
نکات امنیتی
- دسترسی فقط از طریق JWT معتبر و با احراز هویت کامل کاربر (میدلور
authWithJwt الزامی است).
- پارامتر
branch (چه در مسیر و چه در کوئری) باید با شناسه مجاز کاربر احراز هویت شده تطابق داشته باشد (Authorization Check). دسترسی به تنظیمات شعبهای دیگر بدون داشتن دسترسی مدیریتی ممنوع است.
- در صورت استفاده از نوع
hub، دادههای حساس مالی (Markupها) باید فقط برای نقشهای دارای سطح دسترسی admin یا finance_manager بازگردانده شوند. برای نقشهای operator باید دسترسی به این بخش محدود شود.
- اعتبارسنجی ورودیها (Input Validation) برای اطمینان از اینکه
{type} یکی از مقادیر مجاز است، حیاتی است تا از تزریق کدهای دیتابیسی جلوگیری شود (اگرچه استفاده از ORM این خطر را کاهش میدهد).
نکات عملکردی
- Caching: در حالت
hub، حجم داده بهدلیل ارسال لیستهای markup برای چندین سرویس (که اغلب ثابت هستند) میتواند زیاد باشد. استفاده از Caching با Redis (با کلید مبتنی بر نوع و شناسه شعبه) با TTL (Time To Live) بین 1 تا 4 ساعت اکیداً پیشنهاد میشود.
- در حالت
accounting، اگر اطلاعات حسابداری شامل سرفصلهای زیاد باشد، اجرای همزمان کوئریهای متعدد به جدول accounting_titles باید با یک کوئری بهینه با استفاده از JOIN یا Eloquent eager loading تجمیع شود تا سربار دیتابیس کاهش یابد.
- TTL کش تنظیمات پایه: برای تنظیمات
application و office که به ندرت تغییر میکنند، TTL کش باید بین 600 ثانیه (10 دقیقه) تا 1800 ثانیه (30 دقیقه) تنظیم شود.
- استفاده از
DB::table()->where(‘branch_id’, $branchId)->first() به جای کوئریهای پیچیده در این Endpoint اولویت دارد.
وابستگیها
use Illuminate\Support\Facades\DB;: برای اجرای مستقیم کوئریهای بهینه (در صورت نیاز).
use Illuminate\Http\Request;: برای دسترسی به پارامترهای ورودی و بدنه درخواست.
use Carbon\Carbon;: برای مدیریت زمان و تولید Timestamp (در بخش متا).
use App\Services\CacheService;: برای مدیریت لایه کشینگ (Redis).
use Illuminate\Support\Facades\Auth;: برای استخراج اطلاعات کاربر احراز هویت شده از JWT.
کدهای خطا
| کد HTTP |
شرح خطا |
منبع پردازشی |
| 401 |
توکن JWT نامعتبر یا منقضی شده است |
authWithJwt Middleware |
| 403 |
دسترسی به تنظیمات شعبه مجاز نیست |
Authorization Check (درون Controller) |
| 404 |
نوع تنظیمات یافت نشد یا نامعتبر است (مثلاً {type} = ‘billing’ که تعریف نشده است) |
indexSettings() Logic Switch |
| 400 |
پارامتر Branch یا Type در درخواست موجود نیست |
Request Validation |
| 500 |
خطا در واکشی داده از پایگاه داده (مثلاً قطعی اتصال) |
DB facade / ORM Execution |
پیشنهادهای امنیتی
- جداسازی Role در Hub: پیادهسازی چک دقیق Role-Based Access Control (RBAC) برای محتوای
hub. اگر کاربر نقش operator دارد، نباید ضرایب Markup سرور (System Markup) را مشاهده کند.
- Audit Logging: ثبت هر درخواست موفق و ناموفق در جدول
api_logs با جزئیات operator_id، branch_id، endpoint و response_time. نوع لاگ برای درخواستهای موفق باید Info باشد.
- Rate Limiting: افزودن محدودیت نرخ (Rate Limiting) به این مسیر (مثلاً 100 درخواست در هر 5 دقیقه) برای جلوگیری از حملات DDoS یا تلاشهای مکرر برای خواندن دادههای کش نشده.
- Data Sanitization: اگرچه تنظیمات معمولاً از ورودی کاربر نمیآیند، اما اطمینان از عدم بازگرداندن اسکریپتهای خطرناک در فیلدهای متنی (مانند
footer_announcements) ضروری است.
پیشنهادهای بهبود
- تجمیع دادههای Hub Markup: به جای واکشی جداگانه برای هر نوع سرویس در زمان درخواست، یک جدول واحد برای Markupها تعریف شود که شامل یک ستون نوع (Type) باشد. این امر سرعت واکشی را با یک کوئری بهبود میبخشد و مدیریت آن را آسانتر میکند.
- Versioning Settings: افزودن مکانیزمی برای نسخهبندی تنظیمات (مثلاً
settings_version). هنگام تغییر، یک نسخه جدید ثبت شود و در صورت نیاز بتوان به نسخههای قبلی بازگشت (Rollback).
- Endpoint بهروزرسانی مجزا: این مسیر صرفاً خواندنی است. پیشنهاد میشود برای مدیریت بهتر، endpointهای اختصاصی و امن برای بروزرسانی هر بخش (مثلاً
PUT /api/v2/settings/update/accounting) ایجاد شود که فقط توسط مدیران سیستم قابل دسترسی باشند.
- استفاده از DTOها: تبدیل دادههای استخراج شده از DB به Data Transfer Objects (DTOs) قبل از ارسال در پاسخ JSON برای تضمین ساختار یکپارچه خروجی.
ممیزی و لاگها
- هر دسترسی موفق باید در جدول
system_audits با فیلدهای user_id، branch_id، action (‘READ_SETTING’)، و resource (‘settings/{type}’) ثبت گردد.
- در صورتی که داده از کش (Cache Hit) بازگردانده شود، باید یک فیلد
cache_status: HIT در متا اضافه شود. اگر از دیتابیس خوانده شود، cache_status: MISS.
- نوع لاگ پیشفرض برای این Endpoint در Log Service باید Info باشد، مگر اینکه خطا از سطح احراز هویت (401/403) باشد که باید Warning یا Error در نظر گرفته شود.
جمعبندی
مسیر /settings/index/{type} نقطهٔ مرکزی برای واکشی تنظیمات سیستم در سطوح مختلف دفترکار است و نقش حیاتی در پایداری و سازگاری عملیات روزانه دارد. این مسیر ستون فقرات مدیریت پیکربندیها در نسخه Enterprise محسوب میشود. برای پایداری بهتر و کاهش سربار، پیادهسازی مکانیزم Caching با Redis برای انواع hub و application ضروری است. همچنین، کنترل دقیق نقش و سطح دسترسی (Role Check) برای جلوگیری از افشای تنظیمات حساس مالی (بخش accounting و hub) به کاربران غیرمجاز، بالاترین اولویت امنیتی در نگهداری این endpoint را دارد.