#P1397
POST /api/v2/trade/search
Route Info
| Method |
Endpoint |
Controller |
Middleware |
Purpose |
| POST |
/api/v2/trade/search |
V2TradeController@searchTrades |
authWithJwt |
جستجوی معاملات/فاکتورها با فیلترهای چندلایه و ترجمه خودکار مسیرها |
منطق عملکرد و مسیر داده
تابع
searchTrades، درخواست را بر اساس فیلترهای
search و
paginate پردازش میکند:
- تبدیل فیلدهای عددی به رشته خالی برای جلوگیری از فیلترینگ بیهدف.
- بررسی کامل ورود from و to؛ در صورت نبود خروجی error (code 1000).
- ساخت ترکیبی از جستجوهای پیشرفته روی معاملات—فیلدهای: تاریخ، شماره رزرو، اپراتور، تعهدکننده، شماره/تاریخ پرواز، محصول، وضعیت، مسیر، درآمد و اطلاعات مسافر؛ از کوئریهای فشرده با شرطهای تو در تو استفاده میشود.
- تمام توصیفهای مسیر (route) با ترجمههای فارسی/انگلیسی زده میشوند؛ مثل "هتل"، "مسیر"، "تور"، "پرواز" با ترکیبهای محصول و جزئیات.
- اطلاعات تکمیلی هر آیتم از Redis یا DB و کلاسهای کمکی خوانده و کش میشود.
- نتیجه نهایی آرایهای از معاملات با جزییات کامل مسیر و اطلاعات مالی است—پاسخ با meta ساختار یافته و صفحهبندی.
ورودیها (Request Fields)
| نام فیلد |
نوع داده |
ضروری |
توضیح |
| branch |
int|string |
بله |
شناسه شعبه فعال |
| operator |
object |
بله |
اپراتور (از JWT middleware) |
| search |
object |
بله |
شی جستجو با فیلدهایی مانند: r، from، to، op، flightno، dt_departure، passenger، status و... |
| paginate |
object |
بله |
پارامترهای صفحه بندی: start، length |
نمونه Search Structure:
{
"branch": 8,
"search": {
"from": "2025-02-01", "to": "2025-02-12",
"status": "1", "flightno": "W51005",
"op": 22, "pledger": "operator-12"
},
"paginate": {
"start": 0,
"length": 15
}
}
خروجی (Response Structure)
| فیلد |
نوع داده |
توضیح |
| items |
array |
آرایهای از معاملات (ساختار زیر) |
| meta |
object |
شاخصهای صفحهبندی (timestamp, total, page, per_page, last_page, current_page) |
ساختار هر آیتم در خروجی:
| فیلد |
نوع |
توضیح |
| datetime |
object |
تاریخ و ساعت صدور معامله |
| type |
object |
نوع محصول و مسیر |
| income |
string |
نوع درآمد |
| route_type |
string |
نوع اصلی خدمت (aircraft, bus, hotel, ...) |
| pledger |
array|null |
تعهدکنندگان معامله با جزئیات |
| route_title |
string |
توضیح مسیر یا هتل یا سرویس، با ترجمه فارسی یا انگلیسی هوشمند |
| operator |
object |
اطلاعات اپراتور ثبتکننده |
| leader |
object |
لیدر مسیر (در صورت وجود) |
| count_passengers |
int |
تعداد مسافرها |
| status |
int |
وضعیت معامله |
| description |
string|false |
توضیح در صورت status=2,5 |
| serial |
int |
شماره رزرو سیستمی |
| factor_id |
int |
شماره رزرو پایه |
| system_serial |
int |
شماره داخلی فاکتور |
| slug |
string |
شناسه مسیر یکتا |
| suppliers |
array |
فهرست تامینکنندهها |
نمونه پاسخ موفق:
{
"items": [
{
"date": { "title": "11/22", "placeholder": "سهشنبه، 1404/12/23 14:32" },
"route_title": "تهران به کیش | W51005",
"type": { "title": "aircraft", "placeholder": "هواپیما" },
"pledger": [ { "Id": 12, "Title": "جواد مقیمی", "Amount": 250000 } ],
"suppliers": [],
...
}
],
"meta": {
"timestamp": 1693905251,
"total": 29,
"page": 15,
"per_page": 15,
"last_page": 2,
"current_page": 2
}
}
نمونه پاسخ خطا (تاریخ ناقص):
{
"error": {
"code": 1000,
"message": "لطفا تاریخ شروع جستجو و پایان جستجو را وارد نمائید."
},
"meta": {
"timestamp": 1693905251
}
}
تحلیل امنیتی و کنترل خطا
- ورود به Route کاملاً وابسته به JWT؛ اگر توکن معتبر نباشد یا کاربر مجاز نباشد، خطای 1002/1003/1004 یا 1005/1006 برمیگردد.
- ساختار ورودی به هیچوجه با Schema validate نمیشود، زمینهساز حملات Injection یا نقض منطق جستجو است.
- اطلاعات تکمیلی و ترجمهشده مسیر از Redis بدون TTL ذخیره میشود—cache poisoning یا stale data ممکن است رخ دهد.
- در پاسخ خطا (date missing)، هیچ جزئیات sensitive داده نمیشود اما سایر باگهای منطقی ممکن است باعث لو رفتن ساختار پایگاه داده شوند.
- اگر سایز صفحهبندی خیلی بزرگ تنظیم شود، منجر به لحظهای شدن مصرف RAM میشود و هیچ کنترل فشاری ندارد.
نکات کارایی و ضعف طراحی
- استفاده مکرر و نادرست از Redis بدون TTL باعث رشد بیرویه cache و سنگینشدن حافظه سرور میشود.
- رجوع مکرر به DB برای اطلاعات supplement (hotel, airline) در هر جستجو، در مسیرهای حجیم باعث افت عملکرد است.
- ساختار جستجو تو در تو باعث سردرگمی منطق ذخیره نتیجه و ترکیب شروطها میشود؛ لازم است Refactor سرویس جستجو انجام شود.
وابستگیهای کلیدی
- use Carbon\Carbon;
- use Morilog\Jalali\Jalalian;
- use Illuminate\Support\Facades\Redis;
- use App\Models\{Factor, FactorItem, Pledger, User, Colleague, Hotel, Airport, City};
- use App\Http\Controllers\Api\Panel\V2\ApiTradeController;
- use App\Http\Controllers\Api\Panel\V2\StaticController;
- use App\Helpers\Functions;
- use CalendarUtils;
کدهای خطا و خروجیهای Exception
| کد خطا |
شرح |
منبع |
| 1000 |
لطفا تاریخ شروع جستجو و پایان جستجو را وارد نمائید. |
searchTrades (application logic) |
| 1002, 1003, 1004 |
User does not have access permission |
authWithJwt |
| 1005 |
Token not provided |
authWithJwt |
| 1006 |
Your token is invalid or expired |
authWithJwt |
| 500 |
Database / Redis Exception → Trace |
searchTrades, middleware |
پیشنهادهای بهبود
- افزودن TTL برای کلیدهای Redis، با حذف اتوماتیک پس از ۵ دقیقه.
- اعمال validation ساختاری روی ورودیها قبل از اجرای search (JSON Schema/DTO).
- جداسازی سرویسی جستجو و ترجمه route برای کد محصول.
- کنترل حد نهایی صفحهبندی (length & start) جهت جلوگیری از سوءاستفاده.
جمعبندی
این Endpoint جستجو، یکی از پرریسکترین و پیچیدهترین نقاط جریان معاملاتی است. قدرت زیادی با منطق ترکیبی و ترجمه هوشمند دارد، اما ضعفهای امنیتی و عملکردی باعث میشود اگر مهندسی نشده باشد، اثرش کشنده باشد. پیشنهاد اکید: جداسازی سرچسرویس، اعتبارسنجی ورودی، و مهار cache.