Skip to main content
#P1681

GET /v2/charter/financial

Charter: Get Financial Report

این اندپوینت یک گزارش مالی جامع و تجمیع‌شده برای یک چارتر خاص (با شناسه main_id) تولید می‌کند. هدف اصلی آن، ارائه یک دید کلی از وضعیت فروش، درآمد، هزینه‌ها و بدهی‌ها با سه دسته‌بندی مجزا است:

  1. بر اساس کلاس/آیتم (Classes): تفکیک مالی بر اساس هر آیتم (مانند کلاس پروازی Y یا اتاق دو تخته).
  2. بر اساس متعهدین (Pledgers): تفکیک مالی برای رزروهایی که توسط یک همکار خاص تعهد شده‌اند.
  3. بر اساس گارانتی‌کنندگان (Warranties): تفکیک مالی برای رزروهایی که تحت گارانتی یک شخص یا شرکت خاص (ثبت شده در سیستم) هستند.
این گزارش برای تحلیل فروش، حسابداری و مدیریت درآمد چارترها کاربرد حیاتی دارد.

 

Request Overview

URL: /v2/charter/financial
Method: GET
Controller: CharterController@financialCharter
Middleware Stack: authWithJwt

Access Control

  • دسترسی معتبر JWT

Query Parameters

Field Type Description
id integer (الزامی) شناسه اصلی چارتر (main_id) که گزارش مالی برای آن درخواست شده است.

Example Request

GET /v2/charter/financial?id=451

Logic Details

فرآیند تولید گزارش در چندین مرحله و با تجمیع داده‌ها از جداول مختلف انجام می‌شود.

۱. شناسایی جداول و واکشی داده‌های اولیه

  • انتخاب دینامیک جداول: ابتدا تابع کمکی getTableCharter(id) فراخوانی می‌شود تا بر اساس نوع چارتر (پروازی یا اقامتی)، نام جداول صحیح (مانند charter_flight_reservations و charter_flight_calculations) مشخص شود.
  • واکشی رزروها: تمام رکوردهای رزرو (که حذف نرم نشده‌اند) مربوط به main_id از جدول رزروها (`reserves`) خوانده می‌شوند.
  • واکشی قیمت خرید: تمام رکوردهای مربوط به آیتم‌های چارتر از جدول محاسبات (`calculations`) خوانده می‌شوند. این رکوردها حاوی اطلاعات قیمت خرید برای هر آیتم هستند.

۲. ساخت نقشه قیمت خرید (Buy Price Map)

  • یک آرایه انجمنی (map) با نام $buyPrice ساخته می‌شود.
  • سیستم روی رکوردهای `calculations` حلقه می‌زند و برای هر `item_id` (که در اینجا `calculation->id` است)، یک ورودی در این نقشه ایجاد می‌کند.
  • هر ورودی شامل قیمت خرید (`buy_adult`, `buy_child`, `buy_infant`) و عنوان آیتم است.
  • پردازش عنوان:
    • اگر عنوان آیتم یک حرفی باشد (مانند کلاس پروازی 'Y')، تابع Functions::getClassName فراخوانی می‌شود تا نام کامل و خوانای کلاس پروازی به دو زبان فارسی و انگلیسی تولید شود.
    • در غیر این صورت (برای آیتم‌های غیر پروازی)، همان عنوان ثبت شده در دیتابیس استفاده می‌شود.

۳. حلقه اصلی و تجمیع داده‌ها

سیستم یک حلقه بر روی تمام رزروهای واکشی شده (`reserves`) اجرا می‌کند و در هر تکرار، عملیات زیر را انجام می‌دهد:

  1. تجمیع بر اساس کلاس/آیتم (Grouping by Class):
    • داده‌های مالی هر رزرو در آرایه $return['classes'] بر اساس item_id آن رزرو تجمیع می‌شود.
    • درون هر item_id، داده‌ها مجدداً بر اساس رده سنی مسافر (`passenger_age_title` که به حروف کوچک تبدیل شده: `adl`, `chd`, `inf`) دسته‌بندی می‌شوند.
    • برای هر رده سنی، مقادیر زیر محاسبه و جمع زده می‌شوند:
      • count: تعداد مسافران.
      • buy: مجموع قیمت خرید (از نقشه $buyPrice خوانده می‌شود).
      • payable: مجموع مبلغ قابل پرداخت (از فیلد JSON `financial` در رکورد رزرو).
      • taxes, commissions, markups: مجموع مالیات، کمیسیون و مارکاپ. این مقادیر با استفاده از تابع کمکی ReservationController::priceHandle محاسبه می‌شوند که می‌تواند مقادیر درصدی یا ثابت را بر اساس مبلغ قابل پرداخت محاسبه کند.
    • یک جمع کل نیز برای هر item_id (بدون تفکیک سنی) در فیلد financial نگهداری می‌شود.

  1. تجمیع بر اساس گارانتی/تعهد (Grouping by Warranty/Pledger):
    • سیستم بررسی می‌کند که آیا رزرو دارای warranty_type و warranty است.
    • اگر warranty_type برابر با `colleague` باشد:
      • این رزرو یک "تعهد" (Pledger) است.
      • اطلاعات همکار از جدول `colleagues` واکشی می‌شود.
      • داده‌های مالی رزرو در آرایه $return['pledgers'] با کلید شناسه همکار (`colleague->id`) تجمیع می‌شود. ساختار تجمیع دقیقا مشابه تجمیع بر اساس کلاس است (با تفکیک سنی و جمع کل).
    • اگر warranty_type برابر با `system` باشد:
      • این رزرو یک "گارانتی" (Warranty) است.
      • اطلاعات گارانتی‌کننده از جدول `charter_warranties` و سپس با join به جدول `colleagues` (برای یافتن مشخصات گارانتی‌کننده) واکشی می‌شود.
      • داده‌های مالی رزرو در آرایه $return['warranties'] با کلید شناسه گارانتی‌کننده تجمیع می‌شود.

۴. خروجی نهایی

  • در نهایت، ساختار داده تجمیع شده $return در فیلد payload یک پاسخ 200 OK قرار گرفته و به کاربر بازگردانده می‌شود.
  • فیلد changes در ساختار خروجی مقداردهی اولیه می‌شود اما در کد فعلی، هیچ داده‌ای در آن قرار نمی‌گیرد و همیشه یک آرایه خالی است.

Response Structure

پاسخ موفق

در صورت موفقیت، سرور یک پاسخ 200 OK با ساختار پیچیده زیر بازمی‌گرداند. این ساختار شامل سه بخش اصلی `classes`, `pledgers`, و `warranties` است.

  • Status Code: 200 OK
  • Body:
    {
      "payload": {
        "classes": {
          "1234": { // Key is the item_id
            "title": {
              "en": "Y | Economy/Coach",
              "fa": "Y | اکونومی - Economy/Coach"
            },
            "age": {
              "adl": { "count": 10, "buy": 10000000, "payable": 12000000, "taxes": 1200000, "commissions": 600000, "markups": 0 },
              "chd": { "count": 2, "buy": 1600000, "payable": 2000000, "taxes": 200000, "commissions": 100000, "markups": 0 },
              "inf": { "count": 1, "buy": 100000, "payable": 150000, "taxes": 15000, "commissions": 0, "markups": 0 }
            },
            "financial": {
              "count": 13,
              "buy": 11700000,
              "payable": 14150000,
              "taxes": 1415000,
              "commissions": 700000,
              "markups": 0
            }
          }
          // ... other classes
        },
        "pledgers": {
          "56": { // Key is the colleague_id
            "title": {
              "fa": "آژانس همکار - علی رضایی",
              "en": "Partner Agency - Ali Rezaei"
            },
            "age": {
              "adl": { "count": 2, "buy": 2000000, "payable": 2400000, "taxes": 240000, "commissions": 120000, "markups": 0 }
              // ... chd, inf
            },
            "financial": {
              "count": 2, "buy": 2000000, "payable": 2400000, "taxes": 240000, "commissions": 120000, "markups": 0
            }
          }
          // ... other pledgers
        },
        "warranties": {
          // Structure is identical to "pledgers", key is guarantor's colleague_id
        },
        "changes": [] // Always an empty array in the current implementation
      },
      "meta": {
        "timestamp": 1733288400
      }
    }

پاسخ خطا

در صورت بروز هرگونه خطا (مانند عدم یافتن چارتر یا خطای دیتابیس) سرور یک پاسخ 400 Bad Request بازمی‌گرداند.

  • Status Code: 400 Bad Request
  • Body:
    {
      "message": "Error details...",
      "trace": [
        // ... Stack trace for debugging ...
      ]
    }

Helper Functions

دو تابع کمکی نقش کلیدی در منطق این اندپوینت دارند:

Functions::getClassName($class, $lang)

این تابع یک کد کلاس پروازی تک حرفی (مانند 'Y', 'C') را به نام کامل و خوانای آن در زبان‌های مختلف (en, fa, ar) تبدیل می‌کند.

ReservationController::priceHandle($price, $values)

این تابع برای محاسبه مقدار پولی مالیات، کمیسیون یا مارکاپ استفاده می‌شود. ورودی آن مبلغ پایه (`price`) و آرایه‌ای از قوانین (`values`) است. هر قانون می‌تواند بر اساس درصد (`percent`) یا یک مبلغ ثابت (`currency`) باشد. تابع مجموع مقادیر محاسبه شده را بازمی‌گرداند.

 0 && $values) {
        foreach ($values as $value) {
            if ($value && isset($value['value'])) { // Direct value structure
                if ($value['value'] > 0) {
                    if ($value['value_type'] == 'percent') {
                        $return += ($price * $value['value']) / 100;
                    } else if ($value['value_type'] == 'currency') {
                        $return += $value['value'];
                    }
                }
            } else { // Nested structure
                foreach ($value as $item) {
                    if (isset($item['value']) && $item['value']) {
                        if ($item['value_type'] == 'percent') {
                            $return += ($price * $item['value']) / 100;
                        } else if ($item['value_type'] == 'currency') {
                            $return += $item['value'];
                        }
                    }
                }
            }
        }
    }
    return $return;
}
  ?>

Flowchart

Start (GET /charter/financial)
Get `id` from query
1. `getTableCharter(id)` to find table names
2. Fetch all reservations (`reserves`)
3. Fetch all calculation items (`calculations`)
Loop `calculations` to build `$buyPrice` map.
Use `getClassName` for titles.
Loop through each reservation in `reserves`
Aggregate financial data into `$return['classes']` based on `item_id` and `age_title`.
Has `warranty_type`?
↓ Yes
Type is 'colleague'?
↓ Yes
Aggregate into `$return['pledgers']`
↓ No ('system')
Aggregate into `$return['warranties']`
↓ No
Do nothing for this group.
End Loop
Return 200 OK with `payload` containing aggregated data
→ On Any Exception
Return 400 with Exception Details