#P1394
GET /api/v2/exam/get
Route Info
| Method |
Endpoint |
Controller |
Middleware |
Purpose |
تگ Swagger |
| GET |
/api/v2/exam/get |
OfficialController@getExam |
domainAccess, ipTrust |
دریافت فرم آزمون (نظرسنجی) برای سفر یا ارزیابی ۳۶۰ درجه همکاران |
tags={"Exam","V2"} |
توضیح عملکرد (Function Logic)
تابع getExam() بر اساس نوع درخواست مشخص میکند که آزمون از کدام شاخه بارگذاری شود:
- نوع ۱:
trip = نظرسنجی خدمات سفر (Trip Survey)
- نوع ۲:
360_degree_feedback = ارزیابی عملکرد همکار به صورت ۳۶۰ درجه
منطق کلی:
- بررسی مقدار
$request->type.
- اجرای مسیر مرتبط متناسب با نوع آزمون.
- در صورت یافتن شرایط واجد، تولید ساختار آزمون شامل سؤالات، هدر، فوتر و فیلدهای جایگزینشده از دادههای مالی یا اطلاعات همکار.
- بازگشت پاسخ JSON شامل
status، time و داده یا پیام خطا.
ورودیها (Request Parameters)
| پارامتر |
محل |
نوع داده |
الزامی |
توضیح |
| type |
Query |
string |
بله |
نوع آزمون؛ مقدارهای مجاز: "trip" یا "360_degree_feedback". |
| id |
Query |
string|int |
بله |
شناسه مرجع آزمون (Slug سفر یا شناسه همکار). |
| branch |
Query |
string|int |
بله |
کد شعبه فعال (برای محدودسازی دامنه آزمون). |
| operator |
Header/Auth Context |
object |
اختیاری* |
در حالت ۳۶۰ درجه برای تشخیص کاربر واردشده مورد نیاز است. |
الف) جریان عملکرد نوع «trip»
- یافتن فاکتور از جدول
factors بر اساس slug دادهشده.
- بررسی وجود پاسخ قبلی در جدول
exam_response با فیلدهای: object_type='reference' و object=factor.id. اگر وجود داشته باشد → پیغام «این سفر قبلاً نظرسنجی شده است.».
- در غیراینصورت:
- دریافت داده مالی از Redis با کلید
reference:{id}:information. در صورت عدم وجود، صدا زدن TradeController::financial() و ذخیره در Redis.
- واکشی کالاهای موجود در فاکتور از جدول
factor_items.
- یافتن آزمون فعال با
type=trip_survey برای همان شعبه.
- دریافت سؤالات فعال از
exam_questions مرتبشده بر اساس order و id.
- اعمال فیلتر سؤالات: اگر موضوع
hotel است، فقط هنگام وجود محصول مرتبط استفاده میشود.
- جایگزینی متغیرهای دینامیک در title، header و footer با متد
replaceExamItem('trip',...).
- ساخت ساختار خروجی نهایی شامل مشخصات آزمون و آرایه سؤالات.
ب) جریان عملکرد نوع «360_degree_feedback»
- بررسی وجود
operator.id؛ اگر کاربر لاگین نکرده → پیام خطا.
- عدم تطابق شناسه خواستهشده با personnel_id کاربر فعلی (جلوگیری از خودارزیابی).
- جستوجوی همکار هدف در جدول
operators با شروط:
branch JSON contains current branch
status = 1، no_feedback = null.
- بررسی اینکه تاریخ استخدام کارمند حداقل ۱ ماه قبل باشد.
- در صورت گذشت شرط: بررسی عدم وجود پاسخ از کاربر فعلی در ۶ ماه اخیر (
exam_response).
- اگر تاکنون پاسخ نداده → واکشی آزمون با
type=360_degree_feedback و branch جاری.
- واکشی سؤالات و تولید ساختار خروجی مشابه نوع trip، با جایگزینی پارامترهای
{colleague} و {position} در title، header و footer.
ساختار پاسخ (Response Structure)
| فیلد |
نوع داده |
توضیح |
| status |
boolean |
نتیجه نهایی تابع. |
| time |
int (unix timestamp) |
زمان پاسخ سرور (بر حسب ثانیه). |
| data |
object|null |
در صورت true حاوی ساختار آزمون کامل است. |
| message |
string|null |
پیغام خطا هنگام بروز استثنا. |
نمونه پاسخ موفق (trip):
{
"status": true,
"time": 1693905000,
"data": {
"id": 15,
"object": 1472,
"title": "نظرسنجی خدمات پرواز",
"header": "مشتری گرامی، لطفاً به سفر خود امتیاز دهید.",
"footer": "با تشکر از همکاری شما",
"created_at": "1402-02-02 00:00:00",
"questions": [
{
"id": 1,
"type": "rating",
"subject": "flight",
"title": "ارزیابی کیفیت پرواز شما",
"options": [1,2,3,4,5],
"description": null,
"mandatory": 1,
"score": 5
}
]
}
}
نمونه پاسخ خطا:
{
"status": false,
"time": 1693905001,
"message": "این سفر قبلا نظرسنجی شده است."
}
تحلیل امنیتی
- ✅ Middleware دوگانه
domainAccess و ipTrust مانع درخواستهای خارج از محدوده مجاز میشود.
- ⚠️ Endpoint فاقد
authWithJwt است؛ در حالت فعلی کاربران ناشناس میتوانند با دانستن slug به آزمون سفر دسترسی یابند. در حالت Production پیشنهاد میشود JWT فعال شود.
- ✅ دادهی حساسی در خروجی وجود ندارد (تنها ساختار آزمون).
- ⚠️ تابع از Redis و DB مستقیم استفاده میکند بدون هندل استثناء؛ خطای Redis میتواند کل عملیات را fail کند.
وابستگیها (Dependencies)
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Redis;
- use Carbon\Carbon;
- use App\Http\Controllers\Api\Panel\V2\TradeController;
ساختار داخلی data در پاسخ موفق
| فیلد |
نوع |
توضیح |
| id |
int |
شناسه آزمون. |
| object |
int |
شناسه مرجع (سفر یا کارمند). |
| title |
string |
عنوان اصلی آزمون. |
| header/footer |
string |
متن معرفی و پایان آزمون. |
| questions |
array |
لیست سؤالات با فیلدهای id, type, subject, title, options, description, mandatory, score. |
پیغامهای خطای محتمل
- ⚠️ "لینک نظرسنجی معتبر نمی باشد" → شناسه یا کاربر نامعتبر.
- ⚠️ "بانک سوالات تعریف نشده است" → آزمون نوع مربوطه برای این شعبه فعال نشده.
- ⚠️ "این سفر قبلا نظرسنجی شده است" یا "این مورد قبلا نظرسنجی شده است" → پاسخ قبلی موجود است.
- ⚠️ "این کارمند هنوز به مرحله ارزیابی 360 درجه نرسیده" → کمتر از ۱ ماه از ایجاد حساب کارمند گذشته.
- ⚠️ "شما امکان ارائه نظر به خود را ندارید" → جلوگیری از Self Feedback.
- ⚠️ "این نظرسنجی احتیاج به ورود به سیستم دارد." → بدون Auth.
- دسترسی Redis برای کش اطلاعات فاکتور سرعت واکشی آزمون را افزایش میدهد.
- اما هر بار بررسی DB + Redis روی مسیر عمومی ریسک افزایش تاخیر دارد.
- پیشنهاد: تجمیع دادهها در یک Service Layer با TTL منطقی ۵ دقیقهای برای Redis Keyها.
پیوست نگهداری و توسعه بعدی
- انتقال Logic از Controller به Service مستقل (ExamService) جهت پوشش Exception Handling.
- افزودن فیلد
category یا tag به آزمونها جهت فیلتر بهتر در سامانه آموزش.
- درخواست بعدی (POST /api/v2/exam/response) جهت ثبت پاسخ آزمون، مکمل همین Endpoint است و بلافاصله باید مستند شود.