Skip to main content
#P1396

POST /api/v2/trade/list

Route Info

Method Endpoint Controller Middleware Purpose نسخه
POST /api/v2/trade/list V2TradeController@getTradesList authWithJwt نمایش فهرست معاملات (فاکتورها) با فیلترهای پیشرفته Enterprise V1.1

منطق عملکرد تابع

تابع getTradesList لیست فاکتورها (تراکنش‌ها / معاملات) را برای شعبهٔ جاری واکشی می‌کند. در ابتدا داده‌های ورودی از پارامتر json تجزیه می‌شوند؛ شامل تنظیمات DataTable مانند start، length، draw و فیلترهای advanced. اگر کاربر هیچ جستجویی انجام نداده باشد، سیستم به‌صورت پیش‌فرض فقط فاکتورهای همان روز را نمایش می‌دهد. سپس مجموعه‌ای از شرایط فیلترینگ اعمال می‌شود:
  • فیلتر نوع پیشرفته (advanced) بر اساس شماره رزرو (r)، محدوده تاریخ (from, to), اپراتور، وضعیت، شماره پرواز، وسیله، تعهد‌کننده، مسیر و درآمد.
  • محاسبه و ترکیب چندین آرایهٔ ID برای محدودسازی نتایج: $arr_id_fn, $arr_id_d, $arr_id_fu_d, $arr_id_p.
  • اعمال محدودیت دسترسی (Access Control) بر اساس سطح دسترسی اپراتور از طریق تابع Functions::getAccessUser('trade', ...).
  • اتصال به Redis جهت کش (cache) اطلاعات مالی و تعهدکنندگان هر فاکتور با کلیدهای reference:{id}:pledgers و reference:{id}:information.
  • محاسبهٔ شاخص‌های مالی کل برای لیست بازگشتی: مجموع خرید، فروش، سود، بدهی، بستانکاری، تخفیف، تسهیلات، تعداد مسافر.
  • بازچینی داده برای هر معامله به صورت ساختارمند در قالب items[] (جهت نمایش جدول).
  • خروجی استاندارد DataTable-compatible شامل فیلدهای draw, recordsTotal, recordsFiltered, total, و data[].

ورودی‌ها (Request Fields)

نام فیلد نوع داده الزامی توضیح
branch int|string بله شناسه شعبه‌ای که اپراتور به آن متصل است
operator object بله شیء اپراتور استخراج‌شده از JWT
json object (JSON string) بله حاوی ساختار DataTable شامل start، length، draw و فیلترهای advanced

ساختار فیلتر پیشرفته (advanced):

"advanced": {
  "r": "", "from": "2025-01-01", "to": "2025-01-31",
  "op": 0, "status": 1, "flightno": "W51123", "dt_departure": "2025-01-12",
  "pledger": "colleague-42", "vehicle": "aircraft", "income": "", "route": ""
}

خروجی (Response)

فیلد نوع داده توضیح
draw int شماره فراخوان DataTable
recordsTotal int تعداد کل فاکتورها مطابق فیلتر
recordsFiltered int تعداد پس از فیلترینگ
total object مجموع کل شاخص‌های مالی (Buy, Sale, Profit, …)
data array آرایه‌ای از معاملات شامل جزئیات Route، Operator، Pledger و Financial

نمونه درخواست:

POST /api/v2/trade/list
Authorization: Bearer {JWT_TOKEN}
Content-Type: application/json

{
  "branch": 8,
  "json": {
    "draw": 1,
    "start": 0,
    "length": 15,
    "search": {"value": ""},
    "advanced": {"from":"2025-01-01","to":"2025-01-31","status":"1"}
  }
}

نمونه پاسخ:

{
  "draw": 1,
  "recordsTotal": 52,
  "recordsFiltered": 52,
  "total": {
    "Buy": 9200000,
    "Sale": 11300000,
    "Profit": 2100000,
    "Debit": 150000,
    "Credit": 280000,
    "Discount": 30000,
    "Passenger": 91
  },
  "data": [ { "SerialId": 2048001, "Income":"direct", "RouteTitle":"پرواز تهران-کیش", ... } ]
}

امنیت و کنترل دسترسی

  • لایهٔ امنیتی JWT توسط میدل‌ور AuthWithJWT، بررسی توکن و اعتبار کاربر از جداول مختلف (operators, customers, colleague_auth).
  • اگر کاربر غیرفعال باشد یا JWT منقضی شده باشد → Error Code 1002 یا 1006.
  • هیچ Permissions Role-Based دقیق برای فیلدهای مالی در Endpoint اعمال نمی‌شود، فقط سطح general access کنترل می‌شود.
  • اطلاعات مالی از Redis کش خوانده شده و فاقد رمزنگاری است. خطر افشای اطلاعات مالی وجود دارد.
  • هیچ validation روی ساختار داخلی json اعمال نشده — ممکن است دادهٔ تزریق‌شده منجر به crash شود.

نکات کارایی و پیاده‌سازی

  • پنج درخواست مجزا به DB در هر ثبت معامله (Factor + FactorItem + Pledger + Redis fetch/write).
  • NULL caching در Redis هرگز منقضی نمی‌شود، حافظه بدون مدیریت رشد می‌کند.
  • در صورت آغاز بدون فیلتر، تمام روز جاری اسکن می‌شود (query سنگین بدون ایندکس مناسب).
  • محاسبه‌های مالی مجدد زمانی انجام می‌شود که Cache خالی باشد → افزایش CPU.
  • درخواست‌های موازی بدون کنترل Lock روی Redis باعث Out-of-sync در Cache می‌شود.

وابستگی‌ها

  • use Carbon\Carbon;
  • use Morilog\Jalali\Jalalian;
  • use Illuminate\Support\Facades\Redis;
  • use Illuminate\Support\Facades\DB;
  • use App\Models\{Factor, FactorItem, Pledger, User, Colleague};
  • use App\Http\Controllers\Api\Panel\V2\ApiTradeController;
  • use App\Http\Controllers\Api\Panel\V2\TradeController;
  • use App\Http\Controllers\Api\Panel\V2\StaticController;
  • use App\Helpers\Functions;

کدهای خطا و خروجی‌های Exception

کد خطا شرح منبع
1005 Token not provided AuthWithJWT
1006 Your token is invalid or expired AuthWithJWT
1002 / 1003 / 1004 User does not have access permission AuthWithJWT
500 Database / Redis Exception → Trace exposed V2TradeController@getTradesList

پیشنهادهای امنیتی

  • افزودن expiration به Redis cache (TTL 10m).
  • قرار دادن validation برای json input و advanced filters.
  • پنهان‌سازی جزئیات trace در پاسخ خطا.
  • محدودسازی سطح اطلاعات مالی بر اساس Role.

پیشنهادهای بهبود

  • Refactor منطق فیلترینگ در QueryBuilder جداگانه (TradeQueryService).
  • ایجاد ایندکس ترکیبی روی فیلدهای created_at، status و branch.
  • استانداردسازی خروجی Financial در endpoint مستقل.
  • کاهش حجم response با pagination سمت سرور واقعی (بدون pull تمام ستون‌ها).

ممیزی دسترسی و عدم قطعیت

  • دسترسی‌ها با Functions::getAccessUser کنترل می‌شوند اما audit در سطح route وجود ندارد.
  • هیچ log مشخصی برای view یا export ثبت نمی‌شود؛ باید logViewTrade اضافه شود.

جمع‌بندی

این Endpoint یکی از مرکزی‌ترین بخش‌های سیستم حسابداری تجاری است. امنیت پایه‌ای به لطف JWT حفظ شده اما حجم داده بزرگ، منطق فیلتر پیچیده و عدم validation ورودی می‌تواند منبع اشکالات عملکردی یا امنیتی شود. برای تبدیل این منطق به ساختار enterprise-grade، نیاز به جداسازی cache layer، اضافه‌کردن input schema validation و تعریف audit trail قطعی است.